-- SPDX-License-Identifier: GPL-3.0-or-later
---@class LangAI: AI
-- InvaliditySkill = require "lua.core.skill_type.invalidity"
-- ProhibitSkill = require "core.skill_type.prohibit"
---------------------------此AI脚本针对军八卡组，浪系列卡组进行优化，其他加入卡组需要在下面配置表和写对应逻辑实现----------------------------
local LU = require "packages/lang/LUltiity"
local BasicAI = require "packages/lang/AI/BasicAi"
local LangAI = BasicAI:subclass("LangAI")
local AiSkillsData = require "packages/lang/AI/AISkillsData"
LangAI.ISTRUE = true --没什么意义，确认该配表技能名的存在
LangAI.ISFALSE = false 
LangAI.ISFRIEND = "friend" --针对队友的技能配表（配置表看下方）
LangAI.ISENEMY = "enemy" --针对敌人的技能配表
LangAI.INVOKENORMAL = 1 --询问技，通过配表来分辨敌友是否发动
LangAI.INVOKESPECIAL = 2 --询问技，单独用表写函数实现对应逻辑（invokeBySpec表）
--目标身份是否和ai同一个阵营
LangAI.CAMPS = {lord = 1,loyalist = 1,rebel = 2,renegade = 3} 
LangAI.ISSAMECAMP = function(player,target)
  return LangAI.CAMPS[player.role] == LangAI.CAMPS[target.role]
end
--回血或濒死回血卡牌
LangAI.RECCARDS = {analeptic=LangAI.ISTRUE,peach=LangAI.ISTRUE}
--给表属性计数
LangAI.CNTTNUM = function(tb) 
  local n = 0
  if not next(tb) then
    return n
  end
  for k,v in pairs(tb) do
    n = n + 1
  end
  return n
end
--检测是否有某类型技能
LangAI.CheckSelfStatusSkill = function(pr,card)
 local status_skills = Fk:currentRoom().status_skills[TargetModSkill] or Util.DummyTable
  for _, skill in ipairs(status_skills) do
    if skill:bypassTimesCheck(pr, card.skill, Player.HistoryPhase, card,pr) then return true end
  end
  return false
end
----------------------AI技能配置表，让ai技能指向目标更合理（同名技能只写后缀真名，一般是“__”后面的拼音。比如想要写入界郭嘉的遗迹：ex__yiji,那只要写后缀yiji）-----------------------------
--技能黑名单，让一些技能永远不发动
LangAI.BLACKSKILLS = AiSkillsData:getBlackSkills()
--技能选项根据敌友目标选择合理选项（不用真名，优先找mustchose）
LangAI.SKILLCHOICE = AiSkillsData:getSkillChoice()
--针对敌人的技能表
LangAI.SELENEMYBYCHOOSE = AiSkillsData:getSelEnemyByChoose()
--针对队友的技能表
LangAI.SELFRIENDBYCHOOSE = AiSkillsData:getSelFriendByChoose()
--询问技能是否发动（技能指向目标skilltar=LangAI.ISFRIEND是向队友发动，skilltar = LangAI.ISENEMY向敌人发动。如果促使发动技能的来源目标是队友且不对队友发动后面补isjudge=true，例如：贞烈）
LangAI.INVOKESKILL = AiSkillsData:getInvokeSkills()
--触发选牌技，让一些技能选择取消对ai比较友好
LangAI.CANCELSELCARD = AiSkillsData:getCanCelSelCard()
--不需要消耗牌的转化是为技
LangAI.NOCARDVSSkills = AiSkillsData:getNoCardVsSkills()
--用牌智能指向多人的技能
LangAI.MUTITARSBYCARD = AiSkillsData:getMutitarsByCard()
----------------------AI技能配置，让它更智能一些（同名技能只写后缀真名，一般是“__”后面的拼音。比如想要写入界郭嘉的遗迹：ex__yiji,那只要写后缀yiji）-----------------------------

----------------------------------------------可对diy牌名通过填表识别敌友-------------------------------------------
--ai优先使用被记录的卡牌,必须是锦囊牌。
local UseRecordCards = {amazing_grace=true,indulgence=true,supply_shortage=true,wdtx_lightning=LangAI.ISTRUE,collateral=LangAI.ISTRUE,snatch = LangAI.ISTRUE,dismantlement = LangAI.ISTRUE,iron_chain = LangAI.ISTRUE,ljsy=LangAI.ISTRUE,ex_nihilo = LangAI.ISTRUE}
local UseNextTrickCards = {savage_assault=true,archery_attack=true,duel=true,fire_attack=true}
--延时锦囊牌（主要给改判技能用的，diy延时锦囊牌请在下方guicai函数里写对应逻辑）
local Delay_Cards = {indulgence=LangAI.ISTRUE,supply_shortage=LangAI.ISTRUE,lightning=LangAI.ISTRUE}
--移动判定区延时锦囊牌根据牌名执行优先顺序
local MoveDelaySeqs = {indulgence=1,supply_shortage=2} 
--ai优先拆敌人装备区武器列表
local DisEmyWeapons = {crossbow = true,rep_crossbow=true,axe = true,poisonous_dagger=true,quenched_blade=true,thunder_blade=true,fm_jingang=true,sw_feijiang=true}
--拆顺优先选敌人装备区的重要装备
local ImporEeuipsType = {Card.SubtypeDefensiveRide,Card.SubtypeArmor,Card.SubtypeTreasure,Card.SubtypeWeapon,Card.SubtypeOffensiveRide} 
--选牌或者弃牌牌名顺序根据配置来执行先后顺序(牌明越靠前越优先选择或弃之。装备统一用TypeEquip来替代)
-- local discards_prio_t = {"lightning","god_salvation","amazing_grace","collateral","supply_shortage","savage_assault","archery_attack","iron_chain","TypeEquip","dismantlement","snatch","duel","ex_nihilo","ljsy","indulgence","jink","nullification","slash","thunder__slash","fire__slash","analeptic","peach"}
-- local discards_prio_t_new = {"lightning","god_salvation","amazing_grace","collateral","supply_shortage","savage_assault","archery_attack","iron_chain","TypeEquip","dismantlement","snatch","duel","ex_nihilo","ljsy","indulgence","slash","thunder__slash","fire__slash","nullification","jink","analeptic","peach"}
local selcards_prio_t = {"indulgence","peach","analeptic","nullification","ljsy","ex_nihilo","duel","savage_assault","archery_attack","fire_attack","snatch","dismantlement","iron_chain","TypeEquip","jink","fire__slash","thunder__slash","slash","supply_shortage","collateral","god_salvation","amazing_grace","lightning"}
local discards_equip_prio_t = {"TypeEquip","lightning","god_salvation","amazing_grace","collateral","supply_shortage","fire_attack","savage_assault","archery_attack","iron_chain","dismantlement","snatch","duel","ex_nihilo","ljsy","indulgence","jink","nullification","slash","thunder__slash","fire__slash","analeptic","peach"}
local discards_prio_slashs_t = {"lightning","TypeEquip","god_salvation","amazing_grace","slash","thunder__slash","fire__slash","collateral","supply_shortage","fire_attack","savage_assault","archery_attack","iron_chain","dismantlement","snatch","duel","ex_nihilo","ljsy","indulgence","jink","nullification","analeptic","peach"}
local discards_prio_jinks_t = {"lightning","TypeEquip","god_salvation","amazing_grace","collateral","jink","nullification","supply_shortage","fire_attack","savage_assault","archery_attack","iron_chain","dismantlement","snatch","duel","slash","thunder__slash","fire__slash","ex_nihilo","ljsy","indulgence","analeptic","peach"}
local discards_prio_slashjinks_t = {"lightning","TypeEquip","slash","thunder__slash","fire__slash","god_salvation","amazing_grace","collateral","nullification","supply_shortage","jink","iron_chain","dismantlement","analeptic","peach","fire_attack","savage_assault","archery_attack","snatch","duel","ex_nihilo","ljsy","indulgence"}

--获得敌我阵营玩家{player}
LangAI.GetPlayersByCamp = function(player,seltars,camp,callback)
  if #seltars == 0 then return {} end
  local tars = {}
  local room = player.room
  local isids = type(seltars[1]) == "number" and true or false
  local handle = function(tarlist,pr)
    if callback then
      if callback(pr) then
        table.insert(tarlist,pr) 
      end
    else
      table.insert(tarlist,pr) 
    end
  end
  for _,pr in ipairs(seltars) do
    local tar = isids and room:getPlayerById(pr) or pr
    if LangAI.ISFRIEND == camp and LangAI.ISSAMECAMP(player,tar) then 
      handle(tars,tar)
    end
    if LangAI.ISENEMY == camp and not LangAI.ISSAMECAMP(player,tar) then 
      handle(tars,tar)
    end
  end
  return tars
end
--装备区排序
LangAI.sortSelEquips = function(player)
  if player.hp < 3 then return 1 / player.hp end
  local dr = player:getEquipment(Card.SubtypeDefensiveRide)
  local ts = player:getEquipment(Card.SubtypeTreasure)
  local ar = player:getEquipment(Card.SubtypeArmor)
  local we = player:getEquipment(Card.SubtypeWeapon)
  local calv = 0
  if we then 
    calv = DisEmyWeapons[Fk:getCardById(we).name] and 0.6 or 0.3
  end
  if ar and Fk:getCardById(ar).name ~= "silver_lion" then calv = calv + 0.7 end
  if ts then calv = calv + 0.8 end
  if dr then calv = calv + 0.6 end
  return calv
end
--通过技能使用卡牌
LangAI.UseCardLogicBySkill = function(self,usecard,data)
  if not usecard then return end
  local usecardname = usecard.type == Card.TypeEquip and "equiplogic" or usecard.trueName
  local usecardlogic = LangAI.UseCardLogic[usecardname]
  local ret = usecardlogic and usecardlogic(self,usecard,data) or LangAI.UseCardLogic["commonuselogic"](self,usecard,data)
  return ret
end
----------------------------------------------ai对diy卡组填表识别敌友-------------------------------------------
local getSelCardsSeq = function(cards,sel_num,selcards_seq,nodiscart_t)
  if #cards <= 1 or #cards == sel_num then return cards end
  local room = Fk:currentRoom()
  local cardsdata = {TypeEquip={}}
  local discard_t = {}
  local myequis = Self.player_cards[Player.Equip]
  local myhands = Self.player_cards[Player.Hand]
  for k,v in ipairs(cards) do
    local card = Fk:getCardById(v)
    if card.type ~= Card.TypeEquip then
      local cdata = cardsdata[card.name]
      if cdata then
        table.insert(cdata,card)
      else
        cardsdata[card.name] = {card}
      end
    else
      if table.contains(myequis,card.id) then
        if card.sub_type == Card.SubtypeOffensiveRide or card.trueName == "silver_lion" or (Self.hp < 3 and #myhands <= #myequis) then
          table.insert(cardsdata.TypeEquip,card)
        end
      else
        table.insert(cardsdata.TypeEquip,card)
      end
    end
  end
  local n = 0
  while #discard_t ~= sel_num do
    for k,cname in ipairs(selcards_seq) do
      local cdatas = cardsdata[cname]
      if cdatas and #cdatas > 0 then
        local selcard = table.remove(cdatas)
        if not nodiscart_t then
          table.insert(discard_t,selcard.id)
          table.removeOne(cards,selcard.id)
          break
        else
          if not nodiscart_t[selcard.name] then
            table.insert(discard_t,selcard.id)
            table.removeOne(cards,selcard.id)
            break
          end
        end
        if #discard_t == sel_num then break end
      end
    end
    n = n + 1
    if n > sel_num then break end
  end
  if #discard_t ~= sel_num then
    local rerands = table.random(cards,sel_num-#discard_t)
    table.insertTable(discard_t,rerands)
    cardsdata = nil
    return discard_t
  else
    cardsdata = nil
    return discard_t
  end
end
--移动装备牌根据装备类型执行优先顺序
local MoveEQSeqs = {Card.SubtypeTreasure,Card.SubtypeDefensiveRide,Card.SubtypeArmor,Card.SubtypeWeapon,Card.SubtypeOffensiveRide} 
local getJudegeData = function(player)
  local judeges = player:getCardIds(Player.Judge)
  local data = {}
  for delay_c, v in pairs(MoveDelaySeqs) do
    for _, id in ipairs(judeges) do
      local c = player:getVirualEquip(id)
      if not c then c = Fk:getCardById(id) end
      if delay_c == c.trueName then
        table.insert(data,{delay_c,id}) 
      end
    end
  end
  return #data > 0 and data[1] or {}
end
--优先拆队友判定区的卡。优先找队友的兵乐(拆顺戏子的筹测)
local prioDismanFriArea = function(player)
  local room = player.room
  local friendtar,movetrick,moveid
  for _,pr in ipairs(room.alive_players) do
    if LangAI.ISSAMECAMP(player,pr) then
      if #pr.player_cards[Player.Judge] > 0 then 
        local mes = getJudegeData(pr)
        if #mes > 0 then friendtar = pr.id movetrick = mes[1] moveid = mes[2] break end
      end
    end
  end
  return friendtar and {friendtar,movetrick,moveid} or nil
end
--卡组里匹配对应条件的卡
LangAI.patByCards = function(avail_cards,patstr,num,discardseq)
  local exp = Exppattern:Parse(patstr)
  local explist = table.filter(avail_cards,function(cid) 
    local card = Fk:getCardById(cid)
    if exp:match(card) then return true end
  end)
  if #explist == 0 then return end
  explist = getSelCardsSeq(explist,num,discardseq or discards_prio_slashs_t)
  return explist
end
--处理room接口的prompt字符串主要是获取目标角色id
local getPlayerIdByPromt = function(data) 
  if not data then return end
  local last,isai,id
  if string.find(data,":%d") then
    last = string.find(data,":%d") + 1
  elseif string.find(data,":-%d") then
    last = string.find(data,":-%d") - 1
    isai = true
  end
  if last then
    local endlast = isai and last + 1 or last
    local n1 = tonumber(string.sub(data,last,endlast))
    local n2 = last  ~= #data and tonumber(string.sub(data,last,endlast+1)) or nil
    id = (n1 and n2) and n2 or n1
  end
  return id
end

local EncodeByPlayCard = function(card,tars,skillname)
  return json.encode{
    card = skillname and json.encode{skill = skillname,subcards = card.id ~= 0 and {card.id} or card.subcards} or (card.id ~= 0 and card.id or card.originid),
    targets = tars or {}
  }
end
-----------------------------------使用牌逻辑-------------------------------------
local useCardLogic = {}
LangAI.UseCardLogic = useCardLogic
--通用出牌
useCardLogic["commonuselogic"] = function(self,card)
  local player,room = self.player,self.player.room
  if card.skill:feasible({}, {}, player, card) then
    return {}
  else
    local selected_targets,avail_targets= {},{} 
    for i = 1,2 do
      avail_targets = table.filter(room.alive_players, function(p)
        return card.skill:targetFilter(p.id, selected_targets, {}, card) --使用牌指向的目标是否合法
      end)
    end
    if #selected_targets > 0 then
      if card.skill:feasible(selected_targets, {}, player, card) then
        return selected_targets
      end
    end
  end
end
--桃子
useCardLogic["peach"] = function(self,card)
  local player,room = self.player,self.player.room
  if #player.player_cards[Player.Hand] <= player:getMaxCards() and player.hp ~= 1 then return end
  if card.skill:feasible({}, {}, player, card) then
    return {}
  end
end
--南蛮入侵
useCardLogic["savage_assault"] = function(self,card,extradata)
  local toenemys,tofriends = 0,0
  local player,room = self.player,self.player.room
  if not card.skill:feasible({}, {}, player, card) then return end
  local responcard = not extradata and "slash" or extradata.responcard
  for _, pr in ipairs(room.alive_players) do
    if player ~= pr and not player:isProhibited(pr,card) then
      if LangAI.ISSAMECAMP(player,pr) then 
        if player:isCardEffectTo(pr,card) then
          if pr.hp < 2 and not table.find(pr.player_cards[Player.Hand],function(cid) 
              local cd = Fk:getCardById(cid)
              return cd.trueName == responcard or cd.trueName == "nullification" 
            end) 
          then return end
          tofriends = tofriends + 1
        end
      else
        if player:isCardEffectTo(pr,card) then
          if pr.hp < 2 and not table.find(pr.player_cards[Player.Hand],function(cid) 
              local cd = Fk:getCardById(cid)
              return cd.trueName == responcard or cd.trueName == "nullification"
            end) 
          then return {} end
          toenemys = toenemys + 1
        end
      end --打南万牌队友低体力少牌情况下不打牌
    end
  end
  if toenemys < tofriends or (toenemys == tofriends and toenemys == 0) then return end
  return {}
end
--万箭齐发
useCardLogic["archery_attack"] = function(self,card)
  return useCardLogic["savage_assault"](self,card,{responcard="jink"})
end
--火攻
useCardLogic["fire_attack"] = function(self,card)
  local player,room = self.player,self.player.room
  if #player.player_cards[Player.Hand] < 2 then return end
  local seltars,hasvinetars = {},{}
  local filtertars = table.filter(room.alive_players, function(pr) 
    if pr:isKongcheng() or LangAI.ISSAMECAMP(player,pr) or not player:isCardEffectTo(pr,card) then return end
    local ret = card.skill:targetFilter(pr.id, seltars, nil, card) --使用牌指向的目标是否满足卡牌条件
    if ret and not player:isProhibited(pr,card) then
      if pr:hasSkill("#vine_skill") then
        table.insert(hasvinetars,pr)
      end
      return true
    end
  end)
  if #filtertars == 0 then return end
  if #hasvinetars > 0 then
    table.sort(hasvinetars,function (a,b) 
      local aret = LU:calPlayerInfo(a)
      local bret = LU:calPlayerInfo(b)
      return aret < bret
    end)
    return {hasvinetars[1].id}
  else
    if #filtertars > 0 then
      table.sort(filtertars,function (a,b) 
        local aret = LU:calPlayerInfo(a)
        local bret = LU:calPlayerInfo(b)
        return aret < bret
      end)
      return {filtertars[1].id}
    end
  end
end
--桃园结义
useCardLogic["god_salvation"] = function(self,card)
  local damfris,damemy = {},{}
  local player,room = self.player,self.player.room
  if not card.skill:feasible({}, {}, player, card) then return end
  for _,pr in ipairs(room.alive_players) do
    if pr:isWounded() then
      if LangAI.ISSAMECAMP(player,pr) then 
        table.insert(damfris,pr.id) 
      else
        table.insert(damemy,pr.id)
      end
    end
  end
  if #damfris > #damemy or (player.hp < 2 and #damemy - #damfris == 0) then 
    return {}
  end
end
--五谷丰登
useCardLogic["amazing_grace"] = function(self,card)
  local damfris,damemy = {},{}
  local player,room = self.player,self.player.room
  if not card.skill:feasible({}, {}, player, card) then return end
  for _,pr in ipairs(room.alive_players) do
    if LangAI.ISSAMECAMP(player,pr) then 
      table.insert(damfris,pr.id) 
    else
      table.insert(damemy,pr.id)
    end
  end
  if #damfris > #damemy then 
    return {}
  else
    if #damemy - #damfris == 1 then
      local nextpr1 = player:getNextAlive()
      -- local nextpr2 = nextpr1:getNextAlive()
      if LangAI.ISSAMECAMP(nextpr1,player) then
        return {}
      end
    end
  end
end
--无中生有
useCardLogic["ex_nihilo"] = function(self,card)
  local player,room = self.player,self.player.room
  if card.skill:feasible({}, {}, player, card) then
    return {}
  end
end
--闪电
useCardLogic["lightning"] = function(self,card)
  local player,room = self.player,self.player.room
  if table.find(room.alive_players,function(pr) return LangAI.ISSAMECAMP(player,pr) and pr.uselighting end) then
    return card.skill:feasible({}, {}, player, card) and {} or nil
  else
    return
  end
end
--联军盛宴
useCardLogic["ljsy"] = function(self,card)
  return useCardLogic["ex_nihilo"](self,card)
end
--过河拆桥
useCardLogic["dismantlement"] = function(self,card)
  local player,room = self.player,self.player.room
  local seltars,delaycdfriends = {},{}
  local filtertars = table.filter(room.alive_players, function(pr) 
    if pr:isNude() or not player:isCardEffectTo(pr,card) then return end
    local ret = card.skill:targetFilter(pr.id, seltars, nil, card) --使用牌指向的目标是否满足卡牌条件
    if ret and not player:isProhibited(pr,card) then
      if LangAI.ISSAMECAMP(player,pr) and #pr.player_cards[Player.Judge] > 0 and table.find(pr.player_cards[Player.Judge],function(cid) 
        local cd = Fk:getCardById(cid)
        return cd.trueName == "indulgence" or cd.trueName == "supply_shortage"
      end) then
        table.insert(delaycdfriends,pr)
      end
      return true
    end
  end)
  if #filtertars == 0 then return end
  if #delaycdfriends > 0 then
    table.sort(delaycdfriends,function (a,b) return a.hp < b.hp end)
    return {delaycdfriends[1].id}
  else
    filtertars = table.filter(filtertars,function(pr) return not LangAI.ISSAMECAMP(player,pr) and #pr.player_cards[Player.Hand] + #pr.player_cards[Player.Equip] > 0 end)
    if #filtertars == 0 then return end
    table.sort(filtertars,function (a,b) 
      local aret = LangAI.sortSelEquips(a) 
      local bret = LangAI.sortSelEquips(b) 
      if aret + bret ~= 0 then
        return aret > bret
      else
        return a.hp < b.hp
      end 
    end)
    return {filtertars[1].id}
  end
end
--顺手牵羊
useCardLogic["snatch"] = function(self,card)
  return useCardLogic["dismantlement"](self,card)
end
--乐不思蜀
useCardLogic["indulgence"] = function(self,card)
  local player,room = self.player,self.player.room
  local seltars = {}
  local filtertars = table.filter(room.alive_players, function(pr) 
    if pr:hasDelayedTrick(card.trueName) or LangAI.ISSAMECAMP(player,pr) then return end
    local ret = card.skill:targetFilter(pr.id, seltars, nil, card) --使用牌指向的目标是否满足卡牌条件
    if ret and not player:isProhibited(pr,card) then
      return true
    end
  end)
  if #filtertars == 0 then return end
  table.sort(filtertars,function (a,b) return #a.player_cards[Player.Hand] > #b.player_cards[Player.Hand] end)
  if #filtertars ~= 1 then
    local nextpr = LU:getNextCampAlive(player,false,table.map(filtertars,function(pr) return pr.id end)) 
    local pritar = filtertars[1]
    if pritar ~= nextpr and nextpr ~= player then
      return pritar.hp - #pritar.player_cards[Player.Hand] < -3 and {pritar.id} or {nextpr.id}
    end
    return {pritar.id}
  else
    return {filtertars[1].id}
  end
end
--兵粮寸断
useCardLogic["supply_shortage"] = function(self,card)
  return useCardLogic["indulgence"](self,card)
end
--铁索连环
useCardLogic["iron_chain"] = function(self,card)
  local player,room = self.player,self.player.room
  local recast = "recast"
  if not table.find(player.player_cards[Player.Hand],function(cid) 
    local cd = Fk:getCardById(cid)
    return cd.is_damage_card and (string.startsWith(cd.name,"fire") or string.startsWith(cd.name,"thunder")) 
  end) then
    return {},recast
  end
  local seltars,ironfriends = {},{}
  local maxtars = card.skill.getMaxTargetNum and card.skill:getMaxTargetNum(player, card) or 1
  local filtertars = table.filter(room.alive_players, function(pr) 
    local ret = card.skill:targetFilter(pr.id, seltars, nil, card) --使用牌指向的目标是否满足卡牌条件
    if ret and not player:isProhibited(pr,card) then
      if LangAI.ISSAMECAMP(player,pr) and pr.chained then
        table.insert(ironfriends,pr)
      end
      return true
    end
  end)
  if #filtertars == 0 then return {},recast end
  if #ironfriends > 0 then
    ironfriends = table.map(ironfriends,Util.IdMapper)
    if #ironfriends >= maxtars then
      return table.random(ironfriends,maxtars)
    else
      return {},recast
    end
  else
    if #filtertars == 1 then return {},recast end
    local sel_filtertars = {}
    local mincalvalue = 2 --该目标计算的血条闪等最小数值
    local pro_tar
    for _,pr in ipairs(filtertars) do
      if not LangAI.ISSAMECAMP(player,pr) and not pr.chained then
        if player:inMyAttackRange(pr) then
          local prvalue = LU:calPlayerInfo(pr)
          if prvalue < mincalvalue then 
            pro_tar = pr 
          end
        end
        table.insert(sel_filtertars,pr)
      end
    end
    if not pro_tar or #sel_filtertars < 2 then 
      return {},recast
    end
    table.removeOne(sel_filtertars,pro_tar)
    table.sort(sel_filtertars,function (a,b) return a.hp < b.hp end)
    return {pro_tar.id,sel_filtertars[1].id}
  end
end
--决斗
useCardLogic["duel"] = function(self,card)
  local player,room = self.player,self.player.room
  local seltars = {}
  local filtertars = table.filter(room.alive_players, function(pr) 
    if LangAI.ISSAMECAMP(player,pr) or not player:isCardEffectTo(pr,card) then return end
    local ret = card.skill:targetFilter(pr.id, seltars, nil, card) --使用牌指向的目标是否满足卡牌条件
    return ret and not player:isProhibited(pr,card)
  end)
  if #filtertars == 0 then return end

  table.sort(filtertars,function (a,b) 
    local aret = LU:calPlayerInfo(a,"slash")
    local bret = LU:calPlayerInfo(b,"slash")
    return aret < bret
  end)
  local selfslashs = #table.filter(player.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)
  local tarslashs = #table.filter(filtertars[1].player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)
  return selfslashs >= tarslashs and {filtertars[1].id} or nil
end
--借刀杀人
useCardLogic["collateral"] = function(self,card)
  local player,room = self.player,self.player.room
  local seltars,weaponfriends,weaponenemys = {},{},{}
  local filtertars = table.filter(room.alive_players, function(pr) 
    if not pr:getEquipment(Card.SubtypeWeapon) or not player:isCardEffectTo(pr,card) or player:isProhibited(pr,card) then return end
    local ret = card.skill:targetFilter(pr.id, seltars, nil, card) --使用牌指向的目标是否满足卡牌条件
    if not ret then return end

    if not LangAI.ISSAMECAMP(player,pr) then
      local enemysatkrange = table.filter(room.alive_players, function(p)
        return LangAI.ISSAMECAMP(p,pr) and p ~= pr and pr:inMyAttackRange(p) 
      end)
      if #enemysatkrange > 0 then
        table.sort(enemysatkrange,function(a,b) 
          local aret = LU:calPlayerInfo(a,"jink")
          local bret = LU:calPlayerInfo(b,"jink")
          return aret < bret
        end)
        local weapon_id = pr:getEquipment(Card.SubtypeWeapon)
        local weapon = Fk:getCardById(weapon_id)
        local weapon_prio = (weapon.prio or 0 ) + (weapon.spe_weaponprio or 0) 
        table.insert(weaponenemys,{pr.id,enemysatkrange[1].id,weapon_prio})
        return true
      end
    end
    if LangAI.ISSAMECAMP(player,pr) and pr:getCardOrSkillByPat("slash","he","prohibitUse") then
      local friendsatkrange = table.filter(room.alive_players, function(p)
        return not LangAI.ISSAMECAMP(p,pr) and pr:inMyAttackRange(p) 
      end)
      if #friendsatkrange > 0 then
        table.sort(friendsatkrange,function(a,b) 
          local aret = LU:calPlayerInfo(a,"jink")
          local bret = LU:calPlayerInfo(b,"jink")
          return aret < bret
        end)
        local weapon_id = pr:getEquipment(Card.SubtypeWeapon)
        local weapon = Fk:getCardById(weapon_id)
        local weapon_prio = weapon.prio or 0
        table.insert(weaponfriends,{pr.id,friendsatkrange[1].id,weapon_prio})
        return true
      end
    end
  end)
  if #filtertars == 0 then return end
  if #weaponfriends > 0 and #weaponenemys == 0 then
    table.sort(weaponfriends,function(a,b) return a[3] > a[3] end)
    return {weaponfriends[1][1],weaponfriends[1][2]}
  end
  table.sort(weaponenemys,function(a,b) return a[3] > a[3] end)
  return {weaponenemys[1][1],weaponenemys[1][2]}
end
--酒
useCardLogic["analeptic"] = function(self,card,data)
  local player,room = self.player,self.player.room
  if not card.skill:feasible({}, {}, player, card) then return end
  if room.current == player and player.phase == Player.Play and data and data.slashto then
    if player.isplaying and player.hand_analepnum > 0 and player.hand_slashnum > 0 then
      if player.hand_slashnum == 1 or player.useslashnum - player:usedCardTimes("slash",Player.HistoryPhase) == 1 then
        local tareid = data.slashto:getEquipment(Card.SubtypeArmor)
        local armor = tareid and Fk:getCardById(tareid) or nil
        if not armor or armor.trueName ~= "silver_lion" then
          return {},nil,card
        end
        local equipid = player:getEquipment(Card.SubtypeWeapon)
        if equipid and Fk:getCardById(equipid).trueName == "qinggang_sword" then
          return {},nil,card
        end
      end
    end
  end
end
--装备
useCardLogic["equiplogic"] = function(self,card,data)
  local player,room = self.player,self.player.room
  local eid = player:getEquipment(card.sub_type)
  if not player:canUseEquip(card.sub_type) or not card.skill:feasible({}, {}, player, card) then return end
  if not eid then return {} end
    
  local equipcard = Fk:getCardById(eid)
  if equipcard.trueName == "silver_lion" then return {} end
    
  local trueName = card.trueName
  if card.sub_type == Card.SubtypeWeapon and trueName ~= equipcard.trueName then
    if trueName == "spear" and player.hand_slashnum == 0 and player:usedCardTimes("slash",Player.HistoryPhase) == 0 then
      return {}
    end
    if (trueName == "rep_crossbow" or trueName == "crossbow") then
      local findenemy = table.find(room.alive_players,function(pr) return not LangAI.ISSAMECAMP(player,pr) and player:inMyAttackRange(pr,-equipcard.attack_range + card.attack_range) end)
      if findenemy then return {} end
    end 

    if equipcard.spe_weaponprio then --功能型武器（ak，青冈，火扇）
      if not table.find(room.alive_players,function(pr) return not LangAI.ISSAMECAMP(player,pr) and player:inMyAttackRange(pr) end) then 
        local findenemy = table.find(room.alive_players,function(pr) return not LangAI.ISSAMECAMP(player,pr) and player:inMyAttackRange(pr,card.attack_range - equipcard.attack_range) end)
        if findenemy then return {} end
      end
    else
      if card.prio > equipcard.prio then
        return {}
      end
    end
  end
  
  if player.repequip then
    if equipcard.sub_type == Card.SubtypeWeapon then
      if card.prio >= equipcard.prio and not equipcard.spe_weaponprio then return {} end
    else
      return {}
    end  
  end 
end
--闪
useCardLogic["jink"] = function(self,card)
  -- local player,room = self.player,self.player.room
  return {}
end
--杀
useCardLogic["slash"] = function(self,card,extradata)--extradata用来测试预使用杀目标临时贴上无限次数属性来反馈人机是否用合理用杀逻辑
  local player,room = self.player,self.player.room
  local seltars = {} 
  local maxtars = card.skill.getMaxTargetNum and card.skill:getMaxTargetNum(player, card) or 1
  local targets 
  if not extradata then
    targets = room.alive_players
  else
    player.isplaying = false
    local datatars = extradata.must_targets or extradata.exclusive_targets
    targets = datatars and table.map(datatars,function(pid) return room:getPlayerById(pid) end) or room.alive_players 
  end
  local filtertars = table.filter(targets, function(pr) 
    if LangAI.ISSAMECAMP(player,pr) then return end
    local ret = card.skill:targetFilter(pr.id, seltars, nil, card,extradata) --使用牌指向的目标是否满足卡牌条件
    return ret and not player:isProhibited(pr,card)
  end)
  if #filtertars == 0 then return end

  table.sort(filtertars,function (a,b) 
     local aret = LU:calPlayerInfo(a,"jink")
     local bret = LU:calPlayerInfo(b,"jink")
     return aret < bret
  end)
  local maxnum = math.min(maxtars,#filtertars)

  local status_skills = room.status_skills[TargetModSkill] or Util.DummyTable

  local canslashtars = {}
  local pos = 1
  while pos <= #filtertars do    
    local tar = filtertars[pos]
    local iscardeff,reasons = player:isCardEffectTo(tar,card)
    if iscardeff then
      if player.isplaying and player.useslashnum == 1 then
        for _, skill in ipairs(status_skills) do
          if skill:bypassTimesCheck(player,card.skill,Player.HistoryPhase,card,tar) then player.useslashnum = 999 break end
          local correct = skill:getResidueNum(player,card.skill,Player.HistoryPhase,card,tar) or 0
          if correct > 0 then
            player.useslashnum = player.useslashnum + correct
          end
        end
      end
      table.insert(canslashtars,tar.id)
    else
      if player.isplaying and reasons then
        local weapon = player:getCardOrSkillByPat(reasons,Player.Hand,"prohibitUse",1)
        if weapon and player:canUseEquip(weapon.sub_type) then return {},nil,weapon end
      end
    end
    if #canslashtars == maxnum then
      local hasanalep = player:getCardOrSkillByPat("analeptic",Player.Hand,"prohibitUse",1)
      if hasanalep then
        local ret,skiname,useanalep = useCardLogic["analeptic"](self,hasanalep,{slashto=tar})
        if ret then
          return ret,skiname,useanalep
        end
      end
      return canslashtars
    end
    pos = pos + 1
  end
end
-----------------------------------使用牌逻辑-------------------------------------
---@param self LangAI
---@param skill ActiveSkill
---@param card Card | nil
local handleNum = function (skill,num)
  if not num then return end
  if type(num) == "number" then
    if num >= 99 then return end
    return num
  elseif type(num) == "function" then
    return num(skill)
  end
end
--主动技选人，（选牌还得优化）
local function useActiveSkill(self, skill, card)
  local room = self.room
  local player = self.player
  --技能选项数据初始化
  if skill.interaction then
    if next(skill.interaction) == nil then  --初始化太操蛋了
      local interaction = skill:interaction()
      skill.interaction = interaction
      if skill.interaction.type == "spin" then
        skill.interaction.data = math.floor(math.random(interaction.from,interaction.to))
      elseif skill.interaction.type == "combo" then
        skill.interaction.data = skill.trueName ~= "guose" and table.random(interaction.all_choices) or "ex__guose_use"
      end
    else
      if skill.interaction.type == "spin" then
        skill.interaction.data = math.floor(math.random(skill.interaction.from,skill.interaction.to))
      elseif skill.interaction.type == "combo" then
        skill.interaction.data = skill.trueName ~= "guose" and table.random(skill.interaction.all_choices) or "ex__guose_use"
      end
    end
  end

  local tcards 
  if skill.expand_pile and player:getPile(skill.expand_pile) and #player:getPile(skill.expand_pile) > 0 then
    tcards = table.clone(player:getPile(skill.expand_pile))
  else
    tcards = player:getCardIds("he")
  end
  -- if skill.name == "ty_ex__paiyi" then  --十周年排异专属优化
  --   if #tcards ==0 or not skill:canUse(player) then return end
  --   local drawphase = player:getMark("ty_ex__paiyi_draw-phase")
  --   local damagephase = player:getMark("ty_ex__paiyi_damage-phase")
  --   if drawphase == 0 then
  --     skill.interaction.data = "ty_ex__paiyi_draw"
  --     return json.encode{
  --       card = json.encode{
  --         skill = skill.name,
  --         subcards = table.random(tcards,1),
  --       },
  --       targets = {player.id},
  --       interaction_data = skill.interaction.data
  --     }
  --   end
  --   if damagephase == 0 then
  --     local tarenemys = table.filter(room:getOtherPlayers(player),function(pr)
  --     if not LangAI.ISSAMECAMP(player,pr) then
  --       return true
  --     end
  --     end)
  --     if #tarenemys == 0 then return end
  --     skill.interaction.data = "ty_ex__paiyi_damage"
  --     local mincardstars = math.min(#tarenemys,#tcards)
  --     tarenemys = table.map(tarenemys,Util.IdMapper)
  --     return json.encode{
  --       card = json.encode{
  --         skill = skill.name,
  --         subcards = table.random(tcards,mincardstars),
  --       },
  --       targets = table.random(tarenemys,mincardstars),
  --       interaction_data = skill.interaction.data
  --     }
  --   end
  -- end
  card = card or Fk:cloneCard'zixing'
  local alivePlayers = room:getAlivePlayers()

  local maxtars = skill:getMinTargetNum()
  local supermaxtars = skill:getMaxTargetNum(player,card)
  if supermaxtars and supermaxtars ~= maxtars then
    maxtars = supermaxtars > #alivePlayers and #alivePlayers or math.min(#alivePlayers,supermaxtars)
  end

  local maxcards = skill:getMinCardNum()
  local supermaxcards = skill:getMaxCardNum()
  if supermaxcards and supermaxcards ~= maxcards then
    maxcards = supermaxcards > 90 and #tcards or math.min(#tcards,supermaxcards)
  end

  local selected_targets = {}
  local selected_cards = {}
  local playergen = Fk:translate(player.general)
  local skilltrue = Fk:translate(skill.trueName)
  p("==================="..playergen.."使用主动技能："..skilltrue.."===================")
  for _ = 0, 1 do
    if skill:feasible(selected_targets, selected_cards, player, card) then break end
    --筛选卡牌
    local pos = 1
    local avacards = {}
    while #tcards > 0 and maxcards and maxcards > 0 and maxcards ~= #selected_cards do
      local curcid = tcards[pos]
      if skill:cardFilter(curcid, selected_cards,selected_targets) then
        table.insert(avacards,curcid)       
      end
      pos = pos + 1
      if pos > #tcards then
        if #avacards == 0 then break end
        if maxcards ~= #tcards then
          table.insertIfNeed(selected_cards,getSelCardsSeq(avacards,1,discards_prio_jinks_t)[1])
        else
          if #avacards == maxcards then
            selected_cards = avacards
            break
          else
            table.insertTableIfNeed(selected_cards,avacards)
          end          
        end
        avacards = {}
        pos = 1
      end
    end
    --筛选角色
    local tpos = 1
    local avatars = {}
    while #alivePlayers > 0 and maxtars and maxtars > 0 and maxtars ~= #selected_targets do
      local curtar = alivePlayers[tpos]
      if not table.contains(selected_targets,curtar.id) and skill:targetFilter(curtar.id, selected_targets, selected_cards, card) then
        local cansel = true
        if LangAI.SELENEMYBYCHOOSE[skill.trueName] and LangAI.ISSAMECAMP(player,curtar) then cansel = false end
        if LangAI.SELFRIENDBYCHOOSE[skill.trueName] and not LangAI.ISSAMECAMP(player,curtar) then cansel = false end
        if cansel then
          table.insert(avatars,curtar)
        end
      end
      tpos = tpos + 1
      if tpos > #alivePlayers then
        if #avatars == 0 then break end
        if maxtars ~= #alivePlayers then
          local jinkname = "jink"
          table.sort(avatars,function (a,b) 
            local aret = LU:calPlayerInfo(a,jinkname)
            local bret = LU:calPlayerInfo(b,jinkname)
            return aret < bret
          end)
          table.insert(selected_targets,avatars[1].id)
        else
          if #avatars == maxtars then
            selected_targets = table.map(avatars,Util.IdMapper)
          else
            avacards = table.map(avatars,Util.IdMapper)
            table.insertTable(selected_cards,avacards)
          end   
          break       
        end
        avatars = {}
        tpos = 1
      end
    end
    if #selected_targets == 0 and #selected_cards == 0 then break end
  end
  if skill:feasible(selected_targets, selected_cards, player, card) then
    local ret = json.encode{
      card = json.encode{
        skill = skill.name,
        subcards = selected_cards,
      },
      targets = selected_targets,
      interaction_data = skill.interaction and (next(skill.interaction) and skill.interaction.data or nil) or nil
    }
    -- print(ret)
    p("===================".."使用成功".."===================")
    return ret
  end
  p("===================".."使用失败".."===================")
  return
end

---@param self LangAI
---@param skill ViewAsSkill
--转化技（把符合条件某张卡转为指向卡）
local function useVSSkill(self, skill, pattern, viewname)
  local player = self.player
  local room = self.room
  local precondition
  if self.command == "PlayCard" and not Fk.currentResponsePattern then --出牌阶段使用转化技是根据pattern来检索可以使用的转化卡
    local gb = string.find(skill.pattern,",")
    if gb then
      gb = string.gsub(skill.pattern,",",";")
    else
      gb = skill.pattern
    end
    local exp = Exppattern:Parse(gb)
    local cnames = {}
    for _, m in ipairs(exp.matchers) do
      if m.trueName then table.insertTable(cnames, m.trueName) end
    end
    if (not gb or gb == "") and skill.interaction and next(skill.interaction) == nil then --类似欢乐荀攸技能，没有pattern但有转化选项
      local interaction = skill:interaction()
      local chcs = interaction and interaction.choices
      if chcs and #chcs > 0 then
        skill.interaction = interaction
        skill.interaction.data = table.random(chcs)
        precondition = skill.interaction.data
      end
    end
    if #cnames == 0 and not precondition then return end
    if #cnames > 0 then
      for _, n in ipairs(cnames) do
        local c = Fk:cloneCard(n)
        if c.trueName ~= "analeptic" then --出牌阶段在其他地方使用酒技能
          precondition = player:canUse(c) and c.trueName
          if precondition then break end
        end
      end
    end
  else --回合外使用转化技根据相应/使用匹配的卡来执行逻辑
    precondition = viewname
  end
  if not precondition then return nil end
  --转化卡选项数据初始化
  if skill.interaction then
    if next(skill.interaction) == nil then  --初始化太操蛋了
      local interaction = skill:interaction()
      local choices = (interaction and interaction.choices and #interaction.choices > 0) and interaction.choices or nil
      if not choices then return end
      skill.interaction.data = #choices > 0 and table.random(choices) or nil
    else
      if type(skill.interaction) == "table" then
        skill.interaction.data = nil
        local interaction = skill.name == "shouli" and Fk.skills[skill.name]:interaction() or skill.interaction
        local choices = (interaction and interaction.choices and #interaction.choices > 0) and interaction.choices or nil
        if not choices then return end
        skill.interaction.data = #choices > 0 and table.random(choices) or nil
      end
    end
    if skill.interaction.data then skill.interaction.data = precondition else return end
  end
  if LangAI.NOCARDVSSkills[skill.trueName] then --转化卡牌不需要真牌
   local ucard = skill:viewAs()
   if ucard then
    local t = LangAI.UseCardLogic[ucard.trueName](self,ucard)
    if t then
      if not viewname then
        return json.encode{
          card = json.encode{
            skill = skill.name,
            subcards = {},
          },
          targets = t,
          interaction_data = skill.interaction and skill.interaction.data or nil
        }
      else
        return {trueName = viewname,skillname = skill.name,selected_cards = {},selected_targets = t,interaction_data = skill.interaction and skill.interaction.data or nil}
      end
    end
   end
   return 
  end
  local selected_cards = {}
  local selected_targets = {}
  local max_try_time = 3
  local pcards = player:getCardIds{ Player.Hand, Player.Equip }
  if skill.expand_pile and player:getPile(skill.expand_pile) and #player:getPile(skill.expand_pile) > 0 then
    pcards = table.clone(player:getPile(skill.expand_pile))
  end
  for _ = 0, max_try_time do
    local avail_cards = table.filter(pcards, function(id)
      return skill:cardFilter(id, selected_cards)
    end)
    if #avail_cards == 0 then break end
    local randcard = getSelCardsSeq(avail_cards,1,discards_prio_jinks_t)[1]
    table.removeOne(pcards,randcard)
    table.insertIfNeed(selected_cards, randcard)
    local ascard = skill:viewAs(selected_cards)
    if ascard and not player:prohibitUse(ascard) then
      if viewname then  --回合外视为技能对指定目标返回这个数据来匹配敌友策略
        return {trueName = viewname,skillname = skill.name,selected_cards = selected_cards,selected_targets = selected_targets,interaction_data = (skill.interaction and skill.interaction.data) and skill.interaction.data or nil}
      end
      local targets = LangAI.UseCardLogic[ascard.trueName](self,ascard)
      if not targets then return end
      selected_targets = targets 
      local ret = json.encode{
        card = json.encode{
          skill = skill.name,
          subcards = selected_cards,
        },
        targets = selected_targets,
        interaction_data = skill.interaction and (next(skill.interaction) and skill.interaction.data or nil) or nil
      }
      return ret
    end 
  end
  return
end

local random_cb = {}
local suit_type = {spade = Card.Spade,club = Card.Club,heart = Card.Heart,diamond = Card.Diamond}
--发送使用其他技能数据
local EnCodeByUseSkill = function(skillname,selcards,seltars,interaction_data)
  local scards = selcards or {}
  local stars = seltars or {}
  return json.encode{
    card = json.encode{
    skill = skillname,
    subcards = scards,
  },
    targets = stars,
    interaction_data = interaction_data or nil
  }
end
--专属优化技能
local singleOptiSkill = {}
--该diy技能函数涉及较多的room传递的技能类型数据，所以有些参数内容不同，需要根据下面random_cb接口参数做参考然后再diy
--self为当前人机脚本LangAI
--skill为技能
--promt为提示
--cancelable为可点击取消
--skillmes为技能的其他data
LangAI.DiySkillLogic = singleOptiSkill
LangAI.EnCodeByUseSkill = EnCodeByUseSkill
-- singleOptiSkill["bingzheng"] = function(self,skill,promt,cancelable,skillmes)
--   local player,room = self.player,self.player.room
--   local fritars = {}
--   local enytars = {}
--   if not skillmes then return "" end
--   for _,id in ipairs(skillmes.targets) do
--     local tar = room:getPlayerById(id)
--     if LangAI.ISSAMECAMP(player,tar) then
--       table.insert(fritars,tar)
--     else
--       table.insert(enytars,tar)
--     end
--   end
--   if #fritars > 0 then table.sort(fritars,function(a,b) return a.hp < b.hp end) return EnCodeByUseSkill(skill.name,{},{fritars[1].id}) end
--   if #enytars > 0 then table.sort(enytars,function(a,b) return #a.player_cards[Player.Hand] > #b.player_cards[Player.Hand] end) return EnCodeByUseSkill(skill.name,{},{enytars[1].id}) end
--   return ""
-- end
---------------回合内主动技优化（始）-----------------
singleOptiSkill["songci"] = function(self,skill,promt,cancelable,skillmes) 
  local player,room = self.player,self.player.room
  local seltars = {}
  for _,pr in ipairs(room.alive_players) do
    local ret = skill:targetFilter(pr.id, seltars)
    if ret then
      if LangAI.ISSAMECAMP(player,pr) and #pr.player_cards[Player.Hand] <= pr.hp then
        table.insert(seltars,pr.id)
        break
      end
      if not LangAI.ISSAMECAMP(player,pr) and #pr.player_cards[Player.Hand] > pr.hp then
        table.insert(seltars,pr.id)
        break
      end
    end
  end
  if #seltars > 0 then return EnCodeByUseSkill(skill.name,{},seltars) end
  return
end
singleOptiSkill["gn_jieying"] = function(self,skill,promt,cancelable,skillmes) 
  local player,room = self.player,self.player.room
  local tars = LangAI.GetPlayersByCamp(player,room:getOtherPlayers(player),LangAI.ISENEMY)
  if #tars > 0 then
    table.sort(tars,function(a,b) return #a.player_cards[Player.Hand] > #b.player_cards[Player.Hand] end)
    return EnCodeByUseSkill(skill.name,{},{tars[1].id}) or ""
  end
end
singleOptiSkill["zunwei"] = function(self,skill,promt,cancelable,skillmes)  --尊位优化
  local player,room = self.player,self.player.room
  local interaction = skill:interaction()
  if #interaction.choices == 0 then return end
  local others = room:getOtherPlayers(player)
  local selchs,interactiondata
  -- skill.interaction.data = nil
  if table.contains(interaction.choices,"zunwei1") then
    table.sort(others,function(a,b) return #a.player_cards[Player.Hand] > #b.player_cards[Player.Hand] end)
    if #others[1].player_cards[Player.Hand] - #player.player_cards[Player.Hand] > 1 then interactiondata = "zunwei1" selchs = others[1].id end
  end
  if table.contains(interaction.choices,"zunwei2") and not selchs then
    table.sort(others,function(a,b) return #a.player_cards[Player.Equip] > #b.player_cards[Player.Equip] end)
    if #others[1].player_cards[Player.Equip] - #player.player_cards[Player.Equip] > 1 then interactiondata = "zunwei2" selchs = others[1].id end
  end
  if table.contains(interaction.choices,"zunwei3") and not selchs then
    table.sort(others,function(a,b) return a.hp > b.hp end)
    if others[1].hp - player.hp > 1 and player:isWounded() then interactiondata = "zunwei3" selchs = others[1].id  end
  end
  if interactiondata then
    return EnCodeByUseSkill(skill.name,{},{selchs},interactiondata)
  end
end
singleOptiSkill["ol_ex__qimou"] = function(self,skill,promt,cancelable,skillmes)  --奇谋优化
  local player,room = self.player,self.player.room
  local cardlist = {
    slash={},
    archery_attack={},
    savage_assault={},
    analeptic = {},
    peach = {}
  }
  for _,cid in ipairs(player.player_cards[Player.Hand]) do
    local card = Fk:getCardById(cid)
    if cardlist[card.trueName] then
      table.insert(cardlist[card.trueName],cid)
    end
  end
  local max = math.max(#cardlist.archery_attack,#cardlist.savage_assault)
  if max > 0 then
    local others = room:getOtherPlayers(player)
    if #others > 2 and ((player.hp > 2) or (player.hp == 2 and #cardlist.analeptic + #cardlist.peach > 0)) then
      return EnCodeByUseSkill(skill.name,{},{},player.hp)
    end
  end
  if #cardlist.slash <= 1 then return end
  if math.abs(player.hp - #cardlist.slash) > 0 then
    return EnCodeByUseSkill(skill.name,{},{},math.min(player.hp-1,#cardlist.slash))
  else
    if #cardlist.analeptic + #cardlist.peach > 0 then
      return EnCodeByUseSkill(skill.name,{},{},player.hp)
    else
      return EnCodeByUseSkill(skill.name,{},{},player.hp-1)
    end 
  end
end
singleOptiSkill["ex__fanjian"] = function(self,skill,promt,cancelable,skillmes)  --反间优化
  local player,room = self.player,self.player.room
  local hands = player.player_cards[Player.Hand]
  if #hands == 0 then return end
  local tars = LangAI.GetPlayersByCamp(player,room.alive_players,LangAI.ISENEMY)
  if #tars == 0 then return end
  table.sort(tars,function(a,b)
    local acards = (#a.player_cards[Player.Hand] + #a.player_cards[Player.Equip]) / 2 + a.hp
    local bcards = (#b.player_cards[Player.Hand] + #b.player_cards[Player.Equip]) / 2 + b.hp
    return acards > bcards
  end)
  if #tars[1].player_cards[Player.Hand] + #tars[1].player_cards[Player.Equip] == 0 then return end
  local givecard = LangAI.patByCards(hands,"^(peach,analeptic)|.|.|.|.|.|.|",1,discards_prio_jinks_t)
  return givecard and EnCodeByUseSkill(skill.name,givecard,{tars[1].id}) or nil
end
singleOptiSkill["ol_ex__qiangxi"] = function(self,skill,promt,cancelable,skillmes)  --强袭优化
  local player,room = self.player,self.player.room
  local seltars = {}
  local mark = player:getMark("ol_ex__qiangxi_targets-phase")
  mark = mark == 0 and {} or mark
  for _,pr in ipairs(room.alive_players) do
    if not LangAI.ISSAMECAMP(player,pr) and not table.contains(mark,pr.id) then
      table.insert(seltars,pr)
    end
  end
  if #seltars > 0 then 
    table.sort(seltars,function(a,b) return a.hp < b.hp end) 
    local weapons = table.filter(player:getCardIds("he"),function(cid) return Fk:getCardById(cid).sub_type == Card.SubtypeWeapon end)
    if #weapons > 0 then
      weapons = {weapons[1]}
    end
    if not table.contains(mark,seltars[1].id) then
      return EnCodeByUseSkill(skill.name,weapons,{seltars[1].id})
    else
      if #seltars > 1 then
        return EnCodeByUseSkill(skill.name,weapons,{seltars[2].id})
      end
    end
  end
end
singleOptiSkill["jiangchi_active"] = function(self,skill,promt,cancelable,skillmes) --将池
  local player,room = self.player,self.player.room
  local hands = player:getCardIds("he")
  if #hands == 0 then return EnCodeByUseSkill(skill.name,{},{},"ty_ex__jiangchi_prohibit-phase") end
  local cards = LU:getPlayerCardNameIds(player,"h",{"ex_nihilo","ljsy","slash"})
  if LangAI.CheckSelfStatusSkill(player,Fk:cloneCard("slash")) then
    return EnCodeByUseSkill(skill.name,{},{},"ty_ex__jiangchi_draw")
  end
  if #cards.slash == 0 then
    return EnCodeByUseSkill(skill.name,{},{},#cards.ex_nihilo + #cards.ljsy == 0 and "ty_ex__jiangchi_prohibit-phase" or "ty_ex__jiangchi_draw")
  else
    if #cards.slash == 1 then
      if #cards.ex_nihilo + #cards.ljsy == 0 then
        return EnCodeByUseSkill(skill.name,{},{},"ty_ex__jiangchi_draw")
      else
        local slashret = LangAI.UseCardLogic["slash"](self,Fk:cloneCard("slash"))
        if slashret and #slashret > 0 then
          return EnCodeByUseSkill(skill.name,getSelCardsSeq(player:getCardIds("he"),1,discards_prio_jinks_t),{},"ty_ex__jiangchi_targetmod-phase")
        else
          return EnCodeByUseSkill(skill.name,{},{},"ty_ex__jiangchi_draw")
        end
      end
    else
      local slashret = LangAI.UseCardLogic["slash"](self,Fk:cloneCard("slash"))
      if slashret and #slashret > 0 then
        return EnCodeByUseSkill(skill.name,getSelCardsSeq(player:getCardIds("he"),1,discards_prio_jinks_t),{},"ty_ex__jiangchi_targetmod-phase")
      else
        return EnCodeByUseSkill(skill.name,{},{},"ty_ex__jiangchi_draw")
      end
    end
  end
end
singleOptiSkill["jiwu"] = function(self,skill,promt,cancelable,skillmes) 
  local player,room = self.player,self.player.room
  local hands = player:getCardIds("he")
  if #hands == 0 then return end
  local interaction = Fk.skills[skill.name]:interaction()
  if not interaction then return end
  local discpriot,hasxuanfeng
  if player:hasSkill("ty_ex__xuanfeng") then
    hasxuanfeng = true
    discpriot = discards_equip_prio_t
  else
    discpriot = discards_prio_jinks_t
  end
  if not player:hasSkill("ol_ex__qiangxi") and ((player.hp > (player.maxHp / 2)) or table.find(room.alive_players,function(pr) return pr ~= player and pr.hp == 1 and not LangAI.ISSAMECAMP(pr,player) end)) then
    local clonehands = hands
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(clonehands,1,discpriot),{},"ol_ex__qiangxi")
  end
  -- if not player:hasSkill("ex__tieji") then
  --   -- skill.interaction.data = "ex__tieji"
  --   local clonehands = table.clone(hands)
  --   return EnCodeByUseSkill(skill.name,getSelCardsSeq(clonehands,1,discards_prio_jinks_t),{},"ex__tieji")
  -- end
  if not hasxuanfeng then
    -- skill.interaction.data = "ty_ex__xuanfeng"
    local clonehands = hands
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(clonehands,1,discpriot),{},"ty_ex__xuanfeng")
  end
  if not player:hasSkill("ol_ex__wansha") then
    local lowhper = table.find(room.alive_players,function(pr) return pr ~= player and pr.hp == 1 and not LangAI.ISSAMECAMP(pr,player) end)
    if lowhper then
      -- skill.interaction.data = "ol_ex__wansha"
      local clonehands = hands
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(clonehands,1,discpriot),{},"ol_ex__wansha")
    end
  end
end
singleOptiSkill["ex__yongjin"] = function(self,skill,promt,cancelable,skillmes) 
  local player,room = self.player,self.player.room
  local emys_equips = 0
  for _,pr in ipairs(room.alive_players) do
    if pr ~= player and not LangAI.ISSAMECAMP(player,pr) then
      local equips = pr.player_cards[Player.Equip]
      if #equips > 0 then
        for i,e in ipairs(equips) do
          if not table.contains(player.player_cards[Player.Equip],e) then
            emys_equips = emys_equips + 1
          end
        end
      end
    end
  end
  if emys_equips > 1 then
    return EnCodeByUseSkill(skill.name,{},{})
  end
  return
end
---------------回合内主动技优化（末）-----------------

--拼点技能深度优化（来源dis_sel_cards技能优先单独优化）
singleOptiSkill["askforPinDian"] = function(self,skill,promt,cancelable,skillmes) 
  local player,room = self.player,self.player.room
  local num = skillmes.num
  local max = 0
  local id
  local hands = player:getCardIds{Player.Hand}
  if #hands == 0 then return "" end
  for _, cid in ipairs(hands) do
    local card = Fk:getCardById(cid)
    if card.number > max then
      max = card.number
      id = card.id
    end
  end
  return id and EnCodeByUseSkill(skill.name,{id},{}) or ""
end

--必选目标和选牌（例如秘技）
singleOptiSkill["miji"] = function(self,skill,promt,cancelable,skillmes) 
  local player,room = self.player,self.player.room
  local tars = LangAI.GetPlayersByCamp(player,room:getOtherPlayers(player),LangAI.ISFRIEND)
  if #tars > 0 then
    local selcards = getSelCardsSeq(player:getCardIds{Player.Hand},player:getLostHp(),discards_prio_jinks_t)
    table.sort(tars,function(a,b) 
      local cala = LU:calPlayerInfo(a,"jink")
      local calb = LU:calPlayerInfo(b,"jink")
      return cala < calb
    end)
    return EnCodeByUseSkill(skill.name,selcards,{tars[1].id})
  end
  return ""
end
singleOptiSkill["juelie"] = function(self,skill,promt,cancelable,skillmes) --绝烈
  local player,room = self.player,self.player.room
  if skillmes.skillName and skillmes.skillName == "juelie" then
    local tar = getPlayerIdByPromt(promt)
    tar = room:getPlayerById(tar)
    local tarhands = tar.player_cards[Player.Hand]
    local hands = player.player_cards[Player.Hand]
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,math.min(#hands,#tarhands),discards_prio_slashs_t),{})
  end
  return ""
end
singleOptiSkill["qingxi"] = function(self,skill,promt,cancelable,skillmes) --倾袭
  local player,room = self.player,self.player.room
  if skillmes.skillName and skillmes.skillName == "ty_ex__qingxi" then
    local hands = player.player_cards[Player.Hand]
    if #hands < skillmes.num or (player.hp / player.maxHp > 0.5 and #hands - skillmes.num < 3 and not table.find(hands,function(cid) return Fk:getCardById(cid).trueName == "jink" end)) then return "" end
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,skillmes.num,discards_prio_slashs_t),{})
  end
end
singleOptiSkill["liuli"] = function(self,skill,promt,cancelable,skillmes) --琉璃
  local player,room = self.player,self.player.room
  local hands = player:getCardIds("he")
  if #hands == 0 then return "" end
  local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISENEMY)
  if #tars > 0 then
    local selcards = getSelCardsSeq(hands,1,discards_prio_slashs_t)
    table.sort(tars,function(a,b) 
      local cala = LU:calPlayerInfo(a,"jink")
      local calb = LU:calPlayerInfo(b,"jink")
      return cala < calb
    end)
    return EnCodeByUseSkill(skill.name,selcards,{tars[1].id})
  else
    local cards = LU:getPlayerCardNameIds(player,"h",{"jink"})
    if #cards.jink > 0 then
      return ""
    else
      tars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISFRIEND)
      if #tars > 0 then
        table.sort(tars,function(a,b) return a.hp > b.hp end)
        if tars[1].hp > 1 and (player.hp / player.maxHp) <= 0.5 then
          local selcards = getSelCardsSeq(hands,1,discards_prio_slashs_t)
          return EnCodeByUseSkill(skill.name,selcards,{tars[1].id})
        end
      end
    end
  end
  return ""
end
--------其他技能处理数据（接口：AskForUseActiveSkill）----------
--------choose_players_skill通用处理（始）----------
singleOptiSkill["choose_players_skill"] = function(self,skill,promt,cancelable,skillmes)  --选择目标角色技能
  local player,room = self.player,self.player.room
  local tname = skillmes and skillmes.skillName and Fk.skills[skillmes.skillName] and Fk.skills[skillmes.skillName].trueName
  local num = skillmes.num or skillmes.min_num
  local pattern = skillmes.pattern
  local seltars = {}
  local selcards = {}
  local current = room.logic:getCurrentEvent()
  if LangAI.SELENEMYBYCHOOSE[tname] or LangAI.SELFRIENDBYCHOOSE[tname] or LangAI.MUTITARSBYCARD[tname] then
    local usecardtotar = {}
    if LangAI.MUTITARSBYCARD[tname] then --这是用牌指向多个目标的技能
      local usecard = current:findParent(GameEvent.UseCard,Self)
      if usecard then
        local datacard = usecard.data[1] and usecard.data[1].card
        if datacard then
          if (datacard.multiple_targets and datacard.is_damage_card) or datacard.trueName == "slash" then
            usecardtotar.totar = 2
          else
            local useret = LangAI.UseCardLogic[datacard.trueName](self,datacard)
            if useret then usecardtotar.totar = #useret == 0 and 1 or 2 end
          end
        end
      end
    end
    if pattern and pattern~="" then --非主动技选人又选牌的
      local hands = player:getCardIds{Player.Hand, Player.Equip}
      -- local cids = table.filter(hands,function (cid)
      --   if skill.cardFilter and skill.cardFilter(skill,cid,selcards) then
      --     table.insert(selcards,cid)
      --     return true
      --   end
      -- end)
      local exp = Exppattern:Parse(pattern)
      local cids = table.filter(hands,function (cid)
        local card = Fk:getCardById(cid)
        return exp:match(card)
      end)
      if #cids > 0 then
        local cardnums = math.min(num or 1,#cids) 
        cids = getSelCardsSeq(cids,cardnums,discards_prio_jinks_t)
        selcards = cids
      end
    end
    local tars = table.map(skillmes.targets,function(pid) return room:getPlayerById(pid) end) 
    local jinkname = "jing"
    table.sort(tars,function(a,b) 
      local aret = LU:calPlayerInfo(a,jinkname)
      local bret = LU:calPlayerInfo(b,jinkname)
      return aret < bret
    end)
    for _, pr in ipairs(tars) do
      if #seltars == num then break end
      local target = pr
      local pid = pr.id
      if LangAI.ISSAMECAMP(player,target) and LangAI.SELFRIENDBYCHOOSE[tname] then
        table.insertIfNeed(seltars,pid)
      end
      if not LangAI.ISSAMECAMP(player,target) and LangAI.SELENEMYBYCHOOSE[tname] then
        table.insertIfNeed(seltars,pid)
      end
      if usecardtotar.totar then
        if usecardtotar.totar == 1 and LangAI.ISSAMECAMP(player,target) then
          table.insertIfNeed(seltars,pid)
        end
        if usecardtotar.totar == 2 and not LangAI.ISSAMECAMP(player,target) then
          table.insertIfNeed(seltars,pid)
        end
      end
    end
    if #seltars > 0 then return EnCodeByUseSkill(skill.name,selcards,seltars) end
    return "" --如果没人那就返回""
  end
end

singleOptiSkill["bihuo"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  local secamp = promt == "#bihuo-plus" and LangAI.ISFRIEND or LangAI.ISENEMY
  local tars = room:getOtherPlayers(room.current)
  table.insert(tars,room.current)
  tars = LangAI.GetPlayersByCamp(player,tars,secamp)
  if secamp == LangAI.ISENEMY and #tars > 0 then
    table.sort(tars,function(a,b) 
      return a:getMark("@bihuo") > b:getMark("@bihuo")
    end)
  end
  return #tars > 0 and EnCodeByUseSkill(skill.name,{},{tars[1].id}) or ""
end
singleOptiSkill["poxi"] = function(self,skill)
  local player,room = self.player,self.player.room
  local seltars = {}
  for _,pr in ipairs(room:getOtherPlayers(player)) do
    if not LangAI.ISSAMECAMP(player,pr) and #pr.player_cards[Player.Hand] > 0 then
      table.insert(seltars,pr)
    end
  end
  if #seltars > 0 then
    table.sort(seltars,function(a,b) return #a.player_cards[Player.Hand] > #b.player_cards[Player.Hand] end)
    return EnCodeByUseSkill(skill.name,{},{seltars[1].id})
  end
end
singleOptiSkill["fenwei"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  local curcard = room.logic:getCurrentEvent().data[1].card
  if curcard and skillmes and skillmes.targets and type(skillmes.targets) == "table" and #skillmes.targets > 0 then
    local addcards = {amazing_grace=1,god_salvation=1,ljsy=1}
    local seltars = {}
    for _,id in ipairs(skillmes.targets) do
      local tar = room:getPlayerById(id)
      if addcards[curcard.trueName] and not LangAI.ISSAMECAMP(player,tar) then
        table.insert(seltars,id)
      end
      if not addcards[curcard.trueName] and LangAI.ISSAMECAMP(player,tar) then
        table.insert(seltars,id)
      end
    end
    if #seltars > 0 then return EnCodeByUseSkill(skill.name,{},seltars) end
  end
  return ""
end
singleOptiSkill["sheyan"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  local curcard = room.logic:getCurrentEvent().data[1].card
  if curcard then
    local seltars = {}
    local specialcard = {duel=true,ex_nihilo=true,fire_attack=true}
    for _,id in ipairs(skillmes.targets) do
      local tar = room:getPlayerById(id)
      if not specialcard[curcard.trueName] then
        if curcard.is_damage_card and LangAI.ISSAMECAMP(player,tar) then table.insert(seltars,tar) end
        if not curcard.is_damage_card and not LangAI.ISSAMECAMP(player,tar) then table.insert(seltars,tar) end
        else
        if curcard.is_damage_card and not LangAI.ISSAMECAMP(player,tar) then table.insert(seltars,tar) end
        if not curcard.is_damage_card and LangAI.ISSAMECAMP(player,tar) then table.insert(seltars,tar) end
      end
    end
    if #seltars > 0 then 
      table.sort(seltars,function(a,b) return a.hp < b.hp end)
      return EnCodeByUseSkill(skill.name,{},{seltars[1].id}) 
    end
  end
  return ""
end
singleOptiSkill["shensu"] = function(self,skill,promt,cancelable,skillmes) 
  local player,room = self.player,self.player.room
  if (string.find(promt,"shensu1") and (player:hasDelayedTrick("indulgence") or #player.player_cards[Player.Hand]< 3)) or (string.find(promt,"shensu3") and player:getMaxCards() >= #player.player_cards[Player.Hand]) then
    local seltars = {}
    for _,pr in ipairs(room:getOtherPlayers(player)) do
      if not LangAI.ISSAMECAMP(player,pr) and not pr:hasSkill("#vine_skill") then
        table.insert(seltars,pr)
      end
    end
    if #seltars > 0 then
      table.sort(seltars,function(a,b) return a.hp < b.hp end)
      seltars = table.map(seltars,Util.IdMapper)
      return EnCodeByUseSkill(skill.name,{},{seltars[1]})
    end
  end
  return ""
end
singleOptiSkill["jieming"] = function(self,skill,promt,cancelable,skillmes)  --界节命优化
  local player,room = self.player,self.player.room
  if skill.name ~= "choose_players_skill" then return "" end
  if skillmes.skillName == "ol_ex__jieming" then
    local friends,enemys = {},{}
    for _,pr in ipairs(room.alive_players) do
      local hands = pr.player_cards[Player.Hand] 
      if LangAI.ISSAMECAMP(player,pr) and (#hands<= pr.maxHp or #hands-pr.maxHp < 3) then table.insert(friends,{pr.id,5-#hands}) end
      if not LangAI.ISSAMECAMP(player,pr) and #hands> pr.maxHp + 2 then table.insert(enemys,{pr.id,#hands-5}) end
    end
    if #friends > 0 then table.sort(friends,function(a,b) return a[2] > b[2] end) end
    if #enemys > 0 then table.sort(enemys,function(a,b) return a[2] > b[2] end) end
    if #friends > 0 and #enemys > 0 then 
      return EnCodeByUseSkill(skill.name,{},friends[1][2] >= enemys[1][2] and {friends[1][1]} or {enemys[1][1]})
    end
    if #friends > 0 then return EnCodeByUseSkill(skill.name,{},{friends[1][1]}) end
    if #enemys > 0 then return EnCodeByUseSkill(skill.name,{},{enemys[1][1]}) end
  else
    if #skillmes.targets == 0 then return "" end
    for _,id in ipairs(skillmes.targets) do
      local tar = room:getPlayerById(id)
      if LangAI.ISSAMECAMP(player,tar) then EnCodeByUseSkill(skill.name,{},{id}) end
    end
  end
  return ""
end
singleOptiSkill["zhengu"] = function(self,skill,promt,cancelable,skillmes)  --镇骨优化
  local player,room = self.player,self.player.room
  local playerhands = player.player_cards[Player.Hand]
  if skill.name == "choose_players_skill" then
    local friends,enemys = {},{}
    for _,pr in ipairs(room:getOtherPlayers(player)) do
      local hands = pr.player_cards[Player.Hand] 
      if LangAI.ISSAMECAMP(player,pr) and #hands <= #playerhands then table.insert(friends,{pr.id,#playerhands-#hands}) end
      if not LangAI.ISSAMECAMP(player,pr) and #hands> #playerhands then table.insert(enemys,{pr.id,#hands-#playerhands}) end
    end
    if #friends > 0 then table.sort(friends,function(a,b) return a[2] > b[2] end) end
    if #enemys > 0 then table.sort(enemys,function(a,b) return a[2] > b[2] end) end
    if #friends > 0 and #enemys > 0 then 
      return EnCodeByUseSkill(skill.name,{},friends[1][2] >= enemys[1][2] and {friends[1][1]} or {enemys[1][1]})
    end
    if #friends > 0 then return EnCodeByUseSkill(skill.name,{},{friends[1][1]}) end
    if #enemys > 0 then return EnCodeByUseSkill(skill.name,{},{enemys[1][1]}) end
  end
end
singleOptiSkill["yajiao"] = function(self,skill,promt,cancelable,skillmes)  --涯角优化
  local player,room = self.player,self.player.room
  local secamp = promt == "#yajiao-choose" and LangAI.ISENEMY or LangAI.ISFRIEND
  local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,secamp)
  return #tars > 0 and EnCodeByUseSkill(skill.name,{},{tars[1].id}) or ""
end
singleOptiSkill["xuanfeng"] = function(self,skill,promt,cancelable,skillmes)  --旋风优化
  local player,room = self.player,self.player.room
  if skill.name == "m_ex__xuanfeng" then 
    return skillmes.choice[1]
  end
  local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISENEMY)
  if #tars > 0 then
    table.sort(tars,function(a,b) return a.hp < b.hp end)
    return EnCodeByUseSkill(skill.name,{},{tars[1].id}) or ""
  end
end
singleOptiSkill["cansi"] = function(self,skill,promt,cancelable,skillmes)  --残肆优化
  local player,room = self.player,self.player.room
  local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISENEMY)
  if #tars > 0 then
    table.sort(tars,function(a,b) return a.hp < b.hp end)
    return EnCodeByUseSkill(skill.name,{},{tars[1].id}) or ""
  end
end
singleOptiSkill["lijian"] = function(self,skill,promt,cancelable,skillmes)  --离间优化
  local player,room = self.player,self.player.room
  local hands = player:getCardIds("he")
  if #hands == 0 then return end
  local tars = LangAI.GetPlayersByCamp(player,room:getOtherPlayers(player),LangAI.ISENEMY,function(pr) return pr:isMale() end)
  if #tars > 1 then
    table.sort(tars,function(a,b)
      return a.hp < b.hp
    end)
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,1,discards_prio_slashs_t),{tars[1].id,tars[2].id})
  elseif #tars == 1 then
    local friends = LangAI.GetPlayersByCamp(player,room:getOtherPlayers(player),LangAI.ISFRIEND,function(pr) return pr:isMale() end)
    if #friends == 0 then return end
    local slashnum = #table.filter(tars[1].player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)
    table.sort(friends,function(a,b) 
      local aret = #table.filter(a.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)
      local bret = #table.filter(b.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)
      return aret > bret
    end)
    if #table.filter(friends[1].player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end) >= slashnum then
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,1,discards_prio_slashs_t),{tars[1].id,friends[1].id})
    end
  end
end
singleOptiSkill["wanggui"] = function(self,skill,promt,cancelable,skillmes)  --望归优化
  local player,room = self.player,self.player.room
  local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,promt == "#wanggui2-choose" and LangAI.ISFRIEND or LangAI.ISENEMY)
  if #tars > 0 then
    table.sort(tars,function(a,b) return a.hp < b.hp end)
    return EnCodeByUseSkill(skill.name,{},{(tars[1] == player and tars[2]) and tars[2].id or tars[1].id}) or ""
  end
  return ""
end
singleOptiSkill["yuanyu"] = function(self,skill,promt,cancelable,skillmes)  --怨语优化
  local player,room = self.player,self.player.room
  local tars = {}
  local targets = room:getOtherPlayers(player, false)
  for _, pr in ipairs(targets) do
    local tar = pr
    if not LangAI.ISSAMECAMP(player,tar) and tar:getMark("@@yuanyu") == 0 then
      table.insert(tars,tar)
    end
  end
  if #tars == 0 and #targets > 0 then
    local enemy = table.find(targets,function(pr) return not LangAI.ISSAMECAMP(player,pr) end)
    if enemy then
      table.insert(tars,enemy)
    end
  end
  local hands
  if #tars > 0 then
    hands = player:getCardIds{Player.Hand}
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,1,discards_prio_slashs_t),{tars[1].id})
  end
end
singleOptiSkill["shandao"] = function(self,skill,promt,cancelable,skillmes)  --善刀优化
  local player,room = self.player,self.player.room
  local tars = LangAI.GetPlayersByCamp(player,room.alive_players,LangAI.ISFRIEND)
  return #tars > 0 and EnCodeByUseSkill(skill.name,{},table.map(tars,function(pr) return pr.id end)) or nil
end
singleOptiSkill["bingqing"] = function(self,skill,promt,cancelable,skillmes)  --秉清优化
  local player,room = self.player,self.player.room
  local secamp = promt == "#bingqing-draw" and LangAI.ISFRIEND or LangAI.ISENEMY
  local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,secamp)
  return #tars > 0 and EnCodeByUseSkill(skill.name,{},{tars[1].id}) or ""
end
singleOptiSkill["ty_ex__ganlu"] = function(self,skill,promt,cancelable,skillmes)  --甘露优化
  local player,room = self.player,self.player.room
  if not skillmes then
    local emytars = LangAI.GetPlayersByCamp(player,room.alive_players,LangAI.ISENEMY)
    local friendtars = LangAI.GetPlayersByCamp(player,room.alive_players,LangAI.ISFRIEND)
    if #emytars == 0 or #friendtars == 0 then return end
    table.sort(emytars,function(a,b) return #a.player_cards[Player.Equip] > #b.player_cards[Player.Equip] end)
    table.sort(friendtars,function(a,b) return #a.player_cards[Player.Equip] < #b.player_cards[Player.Equip] end)
    if #emytars[1].player_cards[Player.Equip] > #friendtars[1].player_cards[Player.Equip] then
      return EnCodeByUseSkill(skill.name,{},{emytars[1].id,friendtars[1].id}) 
    end
  else
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(player:getCardIds("h"),2,discards_prio_jinks_t),{})
  end
end
singleOptiSkill["m_ex__anxu"] = function(self,skill,promt,cancelable,skillmes)  --安恤优化
  local player,room = self.player,self.player.room
  local emytars = LangAI.GetPlayersByCamp(player,room.alive_players,LangAI.ISENEMY,function(pr) return #pr.player_cards[Player.Hand] + #pr.player_cards[Player.Equip] > 0 end)
  local friendtars = LangAI.GetPlayersByCamp(player,room.alive_players,LangAI.ISFRIEND,function(pr) return player ~= pr end)
  if #emytars == 0 or #friendtars == 0 then return end
  local jinkname = "jink"
  table.sort(emytars,function (a,b) 
    local aret = LU:calPlayerInfo(a,jinkname)
    local bret = LU:calPlayerInfo(b,jinkname)
    return aret < bret
  end)
  table.sort(friendtars,function (a,b) 
    local aret = LU:calPlayerInfo(a,jinkname)
    local bret = LU:calPlayerInfo(b,jinkname)
    return aret < bret
  end)
  return EnCodeByUseSkill(skill.name,{},{friendtars[1].id,emytars[1].id})
end
singleOptiSkill["lihuo"] = function(self,skill,promt,cancelable,skillmes)  --离火优化
  local player,room = self.player,self.player.room
  if promt and string.startsWith(promt,"#lihuo-choose") then
    local enemytars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISENEMY)
    if #enemytars == 0 then return "" end
    table.sort(enemytars,function(a,b) return a.hp < b.hp end)
    return EnCodeByUseSkill(skill.name,{},{enemytars[1].id}) 
  end
end
singleOptiSkill["ty_ex__xianzhou"] = function(self,skill,promt,cancelable,skillmes)  --献州优化
  local player,room = self.player,self.player.room
  if not skillmes then
    -- if #player.player_cards[Player.Equip] < 2 then return end
    local friendtars = LangAI.GetPlayersByCamp(player,room.alive_players,LangAI.ISFRIEND)
    if #friendtars == 0 then return end
    local infriends_atkrange = {}
    for _,pr in ipairs(friendtars) do
      if player ~= pr then
        local enemysinfriendatk = table.filter(room.alive_players, function(p)
          return p ~= pr and not LangAI.ISSAMECAMP(p,pr) and pr:inMyAttackRange(p)
        end)
        if #enemysinfriendatk > 0 then
          table.insert(infriends_atkrange,{pr.id,enemysinfriendatk})
        end
      end
    end
    if #infriends_atkrange > 0 then
      table.sort(infriends_atkrange,function(a,b) return #a[2] > #b[2] end)
      return EnCodeByUseSkill(skill.name,{},{infriends_atkrange[1][1]})
    end
  else
    local enemytars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISENEMY)
    if #enemytars > 0 then
      table.sort(enemytars,function(a,b) return a.hp < b.hp end)
      enemytars = table.slice(enemytars,1,math.min(#enemytars,skillmes.num)+1)
      enemytars = table.map(enemytars,Util.IdMapper)
      return EnCodeByUseSkill(skill.name,{},enemytars)
    end
    return ""
  end
end
singleOptiSkill["ol_ex__shizhan"] = function(self,skill,promt,cancelable,skillmes)  --势斩优化
  local player,room = self.player,self.player.room
  local selfslashs = #table.filter(player.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)
  if player.hp / player.maxHp <= 0.5 and selfslashs == 0 then
    return
  end
  local tars = LangAI.GetPlayersByCamp(player,room.alive_players,LangAI.ISENEMY)
  if #tars > 0 then
    table.sort(tars,function (a,b) 
      local aret = LU:calPlayerInfo(a,"slash")
      local bret = LU:calPlayerInfo(b,"slash")
      return aret < bret
    end)
    local tarslashs = #table.filter(tars[1].player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)
    if player.hp / player.maxHp <= 0.5 and selfslashs <= tarslashs then
      return
    end
    return EnCodeByUseSkill(skill.name,{},{tars[1].id})
  end
  return
end
singleOptiSkill["yuguan"] = function(self,skill,promt,cancelable,skillmes)  --御关优化
  local player,room = self.player,self.player.room
  local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISFRIEND)
  if #tars > 0 then
    table.sort(tars,function(a,b)
      return (a.maxHp-#a.player_cards[Player.Hand]) > (b.maxHp-#b.player_cards[Player.Hand])
    end)
    return EnCodeByUseSkill(skill.name,{},{tars[1].id})
  end
  return ""
end
singleOptiSkill["xuanhuo_choose"] = function(self,skill,promt,cancelable,skillmes)  --暄惑优化
  local player,room = self.player,self.player.room
  if promt and promt == "#ty_ex__xuanhuo-invoke" then
    local hands = player:getCardIds("h")
    if #hands < 2 then return "" end
    local friendtars,enemytars = {},{}
    for _, pr in ipairs(room:getOtherPlayers(player)) do
      if LangAI.ISSAMECAMP(player,pr) then
        table.insert(friendtars,pr.id)
      else
        table.insert(enemytars,pr)
      end
    end
    if #enemytars > 0 then
      table.sort(enemytars,function(a,b) return a.hp < b.hp end)
    else
      return ""
    end
    if #friendtars == 0 then return "" end
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,2,discards_prio_jinks_t),{friendtars[1],enemytars[1].id})
  end
end
singleOptiSkill["choose_skill"] = function(self,skill,promt,cancelable,skillmes) --通用选人选派技能（清检）
  local player,room = self.player,self.player.room
  local hands = skillmes.include_equip and player:getCardIds{Player.Hand, Player.Equip} or player:getCardIds{Player.Hand}
  if #hands == 0 then return "" end
  if skillmes.skillName == "ex__qingjian" then
    local tars = room:getAlivePlayers(true)
    table.removeOne(tars,player)
    tars = LangAI.GetPlayersByCamp(player,tars,LangAI.ISFRIEND)
    if #tars > 0 then
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,math.min(2,#hands),discards_prio_jinks_t),{tars[1].id})
    end
  end
  return ""
end
singleOptiSkill["mingce"] = function(self,skill,promt,cancelable,skillmes)  --明策优化
  local player,room = self.player,self.player.room
  if not promt and not skillmes then
    local slashweapons = table.filter(player:getCardIds("he"),function(cid) 
      local card = Fk:getCardById(cid)
      return card.trueName == "slash" or card.type == Card.TypeEquip
    end)
    if #slashweapons > 0 then
      local infriends_atkrange,tofriends = {},{}
      for _,pr in ipairs(room:getOtherPlayers(player)) do
        if LangAI.ISSAMECAMP(player,pr) then
          table.insert(tofriends,pr.id)
          local enemyinfriendatk = table.find(room:getOtherPlayers(pr), function(p)
            return pr:inMyAttackRange(p) and not LangAI.ISSAMECAMP(p,pr) 
          end)
          if enemyinfriendatk then
            table.insert(infriends_atkrange,pr.id)
          end
        end
      end
      if #infriends_atkrange > 0 then
        return EnCodeByUseSkill(skill.name,table.random(slashweapons,1),{infriends_atkrange[1]})
      else
        if #tofriends > 0 then
          return EnCodeByUseSkill(skill.name,table.random(slashweapons,1),{tofriends[1]})
        end
      end    
    end
  end
  if promt and string.startsWith(promt,"#mingce-choose") then
    local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISENEMY)
    if #tars > 0 then
      table.sort(tars,function(a,b) 
        local aret = LU:calPlayerInfo(a,"jink")
        local bret = LU:calPlayerInfo(b,"jink")
        return aret < bret
      end)
      return EnCodeByUseSkill(skill.name,{},{tars[1].id})
    else
      return EnCodeByUseSkill(skill.name,{},table.random(skillmes.targets,1))
    end
  end
  if skillmes and skillmes.choice then
    local tar = getPlayerIdByPromt(skillmes.choice[1])
    if tar then
      tar = room:getPlayerById(tar)
      if LangAI.ISSAMECAMP(player,tar) then
        return skillmes.choice[2]
      else
        local slash = Fk:cloneCard("slash")
        if player:isCardEffectTo(tar,slash) and not player:prohibitUse(slash) then
          return skillmes.choice[1]
        end
      end
    else
      return skillmes.choice[2]
    end
  end
end
singleOptiSkill["wulie"] = function(self,skill,promt,cancelable,skillmes)  --武烈优化
  local player,room = self.player,self.player.room
  local totaltars,hurttars = {},{}
  for _,pr in ipairs(room:getOtherPlayers(player)) do
    if LangAI.ISSAMECAMP(player,pr) then
      table.insert(totaltars,pr.id)
      table.insert(hurttars,pr.id)
    end
  end
  if #hurttars > 1 then
    if player.hp > #hurttars then
      return EnCodeByUseSkill(skill.name,{},hurttars)
    elseif player.hp == #hurttars then
      local peach,analeptic = "peach","analeptic"
      local cards = LU:getPlayerCardNameIds(player,"h",{peach,analeptic})
      if #cards[peach] + #cards[analeptic] > 0 then
        return EnCodeByUseSkill(skill.name,{},hurttars)
      else
        return EnCodeByUseSkill(skill.name,{},table.random(hurttars,#hurttars-1))
      end
    end
  elseif #hurttars == 1 then
    if #totaltars > 1 then
      if player.hp >= 2 then
        -- totaltars = table.filter(totaltars,function(pid) return pid ~= hurttars[1] end) 
        -- table.insert(hurttars,table.random(totaltars))
        return EnCodeByUseSkill(skill.name,{},hurttars)
      end
    else
      if player.hp > 1 then
        return EnCodeByUseSkill(skill.name,{},hurttars)
      end
    end
  end
  return ""
end
--------choose_players_skill通用处理（末）----------

--移动牌技能（接口AskForUseActiveSkill）
singleOptiSkill["choose_players_to_move_card_in_board"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  local moveflag = skillmes.flag
  if not moveflag or (moveflag and string.find(moveflag,"j")) then
    local friendinfo = prioDismanFriArea(player)
    if friendinfo then
      local enemytar = table.find(room.alive_players,function(pr)
        if not LangAI.ISSAMECAMP(player,pr) and not pr:hasDelayedTrick(friendinfo[2]) then
          return true
        end
      end) 
      if enemytar then
        return EnCodeByUseSkill(skill.name,{},{friendinfo[1],enemytar.id})
      end
    end
  end
  local frilist = {}
  local enylist = {}
  local frinoeplist = {}
  local handleEquipArea = function(who,wholist)  --处理所有玩家的装备区牌
    local euiptypes = table.map(who:getCardIds(Player.Equip),function(eid)
      return Fk:getCardById(eid).sub_type
    end)
    if #euiptypes > 0 then
      local sortbycfg = function(nosort_t,cfg)
        local sort_t = {}
        for _,v in ipairs(cfg) do
          for i,t in ipairs(nosort_t) do
            if v == t then table.insert(sort_t,t) end
          end
        end
        return sort_t
      end
      euiptypes = sortbycfg(euiptypes,MoveEQSeqs) --移动装备的类型进行排序
      table.insert(wholist,{id = who.id,euiptypes = euiptypes})
    end
  end
  for k,pr in ipairs(room.alive_players) do
    if LangAI.ISSAMECAMP(player,pr) then
      handleEquipArea(pr,frilist)
      table.insert(frinoeplist,pr.id)
    else
      handleEquipArea(pr,enylist)
    end
  end
  if #enylist > 0 then
    local selprioenemy = {}  --优先筛选有宝物，+1马，防具，武器的敌人
    local selpriofriend = {}  --优先筛选没有宝物，+1马，防具，武器的队友
    local priotyps = {7,5,4,3}
    for _,pmes in ipairs(enylist) do 
      if table.contains(priotyps,pmes.euiptypes[1]) then
        table.insert(selprioenemy,pmes.id)
      end
    end
    if #frilist == 0 then
      selpriofriend = {table.random(frinoeplist)}
    else
      for _,pmes in ipairs(frilist) do 
        if not table.contains(priotyps,pmes.euiptypes[1]) then
          table.insert(selpriofriend,pmes.id)
        end
      end
      if #selpriofriend == 0 then
        selpriofriend = {table.random(frinoeplist)}
      end
    end  
    local enemypid = #selprioenemy > 0 and selprioenemy[1] or table.random(enylist).id
    local friendpid = selpriofriend[1]
    local selswitchtars = {enemypid,friendpid} --移动顺序是先敌人后队友
    return EnCodeByUseSkill(skill.name,{},selswitchtars)
  else
    return ""
  end
end

-------改判定技能优化（AskForResponseCard）（始）-----------
singleOptiSkill["guicai"] = function(self,skill,promt,cancelable,skillmes) --鬼才（通用改判逻辑）
  local player,room = self.player,self.player.room
  local current = room.logic:getCurrentEvent()
  local data = room.logic:getCurrentEvent().data[1]
  if not data then return "" end
  local tar = data.who
  local reason = data.reason
  local pattern = skillmes.pattern
  local is_respon = skill.trueName == "guidao" and true or false
  if reason and string.find(reason,"luoshen") and table.find(player.player_skills,function(s) if s.trueName == "luoshen" then return true end end) then return "" end 

  local exp = Exppattern:Parse(pattern)
  local avail_cards = table.filter(player:getCardIds{Player.Hand, Player.Equip},function(cid)
    local card = Fk:getCardById(cid)
    if exp:match(card) then return true end
  end)
  if #avail_cards == 0 then return "" end
  local retjson = function(expcids)
    return json.encode{
      card = not is_respon and json.encode{
        subcards = expcids,
      } or expcids[1],
      targets = {}}
  end
  if Delay_Cards[reason] then
    if reason == "indulgence" then
      if LangAI.ISSAMECAMP(player,tar) and data.card.suit ~= Card.Heart then
        local expcids = LangAI.patByCards(avail_cards,".|.|heart",1)
        if expcids then return retjson(expcids) end
      end
      if not LangAI.ISSAMECAMP(player,tar) and data.card.suit == Card.Heart then
        local expcids = LangAI.patByCards(avail_cards,".|.|^heart",1)
        if expcids then return retjson(expcids) end
      end
    elseif reason == "supply_shortage" then
      if LangAI.ISSAMECAMP(player,tar) and data.card.suit ~= Card.Club then
        local expcids = LangAI.patByCards(avail_cards,".|.|club",1)
        if expcids then return retjson(expcids) end
      end
      if not LangAI.ISSAMECAMP(player,tar) and data.card.suit == Card.Club then
        local expcids = LangAI.patByCards(avail_cards,".|.|^club",1)
        if expcids then return retjson(expcids) end
      end
    elseif reason == "lightning" then
      if LangAI.ISSAMECAMP(player,tar) and data.card.suit == Card.Spade and data.card.number >= 2 and data.card.number <= 9 then
        local expcids = LangAI.patByCards(avail_cards,".|.|^spade",1)
        if expcids then return retjson(expcids) end
      end
      if not LangAI.ISSAMECAMP(player,tar) then
        local expcids = LangAI.patByCards(avail_cards,".|2~9|spade",1)
        if expcids then return retjson(expcids) end
      end
    end
  elseif reason == "#eight_diagram_skill" then
    if LangAI.ISSAMECAMP(player,tar) and data.card.color ~= Card.Red then
      local expcids = LangAI.patByCards(avail_cards,".|.|heart,diamond",1)
      if expcids then return retjson(expcids) end
    end
    if not LangAI.ISSAMECAMP(player,tar) and data.card.color == Card.Red then
      local expcids = LangAI.patByCards(avail_cards,".|.|spade,club",1)
      if expcids then return retjson(expcids) end
    end
  else
    local truename = Fk.skills[reason] and Fk.skills[reason].trueName or nil
    if not truename then return "" end
    if truename == "leiji" then
      if not LangAI.ISSAMECAMP(player,tar) and data.card.suit ~= Card.Spade then
        local expcids = LangAI.patByCards(avail_cards,".|.|spade",1)
        if expcids then return retjson(expcids) end
      end
    end
  end
  return ""
end
singleOptiSkill["guidao"] = function(self,skill,promt,cancelable,skillmes) --鬼道
  return singleOptiSkill["guicai"](self,skill,promt,cancelable,skillmes)
end
singleOptiSkill["chenjie"] = function(self,skill,promt,cancelable,skillmes) --臣节
  local player,room = self.player,self.player.room
  local current = room.logic:getCurrentEvent()
  local data = room.logic:getCurrentEvent().data[1]
  if not data then return "" end
  local reason = data.reason
  local pattern = skillmes.pattern

  local exp = Exppattern:Parse(pattern)
  local avail_cards = table.filter(player:getCardIds{Player.Hand, Player.Equip},function(cid)
    local card = Fk:getCardById(cid)
    if exp:match(card) then return true end
  end)
  if #avail_cards == 0 then return "" end
  local retjson = function(expcids)
    return json.encode{card = expcids[1],targets = {}}
  end
  local expcids = LangAI.patByCards(avail_cards,pattern,1)
  if expcids then return retjson(expcids) end
  return ""
end
-------判定技能优化（AskForResponseCard）（末）-----------

--------dis_sel_cards技能通用处理（始）----------
--自己弃牌或者选牌技能单独优化（原技能discard_skill,choose_cards_skill，接口AskForUseActiveSkill）
singleOptiSkill["dis_sel_cards"] = function(self,skill,promt,cancelable,skillmes) 
  local player,room = self.player,self.player.room
  if skill.name == "discard_skill" and skillmes.skillName == "game_rule" then
    return singleOptiSkill["discard_skill"](self,skill,promt,cancelable,skillmes)
  end
  local hands = skillmes.include_equip and player:getCardIds{Player.Hand, Player.Equip} or player:getCardIds{Player.Hand}
  if skillmes.expand_pile then 
    hands = player:getPile(skillmes.expand_pile)
  end
  if #hands == 0 then return "" end
  if cancelable and LangAI.CANCELSELCARD[skillmes.skillName] then return "" end
  local tskill = Fk.skills[skillmes and skillmes.skillName]
  if tskill and (LangAI.SELENEMYBYCHOOSE[tskill.trueName] or LangAI.SELFRIENDBYCHOOSE[tskill.trueName]) and type(promt) == "string" then  --触发弃牌技能
    local id = getPlayerIdByPromt(promt)
    local target = room:getPlayerById(id)
    if target then
      if LangAI.SELENEMYBYCHOOSE[tskill.trueName] and LangAI.ISSAMECAMP(player,target) then return "" end
      if LangAI.SELFRIENDBYCHOOSE[tskill.trueName] and not LangAI.ISSAMECAMP(player,target) then return "" end
    end
  end
  -- local discard_t = {}
  local minnum = skillmes.min_num
  local maxnum = skillmes.maxnum
  local num = skillmes.num
  local discard_num = minnum or maxnum or num or 1
  local pattern,exp
  pattern = (skillmes.pattern and skillmes.pattern ~= "") and skillmes.pattern or "."
  exp = Exppattern:Parse(pattern or ".")
  hands = table.filter(hands,function (cid)
    return exp:match(Fk:getCardById(cid))
  end)
  if skill.name == "discard_skill" then
    hands = table.filter(hands,function(cid) return not player:prohibitDiscard(Fk:getCardById(cid)) end)
  end
  if #hands == 0 then return "" end
  if (maxnum and maxnum >= 99) or (num and num >= 99) then
    discard_num = #hands > 4 and math.floor(math.random(2,3)) or 1
  end
  if #hands < discard_num then --牌不够全部弃
    return ""
  end
  --优化弃牌或者选派逻辑
  if room.current == player and player.phase < Player.Discard then
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,discard_num,discards_prio_jinks_t),{})
  else
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,discard_num,player.hp < 3 and discards_prio_slashs_t or discards_prio_slashjinks_t),{})
  end
end
singleOptiSkill["huozhong&"] = function(self,skill)
  local player,room = self.player,self.player.room
  local cantri
  local huozongown
  local sname = "huozhong"
  for _,pr in ipairs(room.alive_players) do
    local skillown = table.find(pr.player_skills,function(s)
      return s.name == sname
    end)
    if skillown and LangAI.ISSAMECAMP(player,pr) then
      cantri = true
      huozongown = pr.id
      break
    end
  end
  if cantri then
    local cardid
    for _,cid in ipairs(player:getCardIds{Player.Hand,Player.Equip}) do
      local card = Fk:getCardById(cid)
      if card.type ~= Card.TypeTrick and card.color == Card.Black then
        cardid = cid
        break
      end
    end
    if cardid then return EnCodeByUseSkill(skill.name,{cardid},{}) end
  end
  return
end
local JiaoJinCards = {"god_salvation","amazing_grace","ljsy","iron_chain"}
singleOptiSkill["jiaojin"] = function(self,skill,promt,cancelable,skillmes) --骄矜优化
  local player,room = self.player,self.player.room
  local logicdata = room.logic:getCurrentEvent().data[1]
  local card = logicdata.card
  if not card then return "" end

  if not table.contains(JiaoJinCards,card.trueName)then
    local handlereply = function()
      if #player.player_cards[Player.Equip] == 0 then return "" end
      local equips = table.map(player.player_cards[Player.Equip],function(cid) return Fk:getCardById(cid) end)
      local selsequence = {Card.SubtypeOffensiveRide,Card.SubtypeWeapon,Card.SubtypeDefensiveRide,Card.SubtypeTreasure,Card.SubtypeArmor}
      local startpos = 1
      while startpos <= #selsequence do
        local subtype = selsequence[startpos]
        for _,cd in ipairs(equips) do
          if subtype == cd.sub_type then
            return EnCodeByUseSkill(skill.name,{cd.id},{})
          end
        end
        startpos = startpos + 1
      end
      return ""
    end
    if card.trueName ~= "slash" then
      local handequips = table.filter(player.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).type == Card.TypeEquip end)
      if #handequips > 0 then
        return EnCodeByUseSkill(skill.name,table.random(handequips,1),{}) 
      else
        if #player.player_cards[Player.Equip] > 0 then
          return handlereply()
        end
      end
    else
      if table.find(player.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "jink" end) then
        return ""
      else
        return handlereply()
      end
    end
  end
  return ""
  -- local indx = string.find(promt,"%d:")
  -- local cardlog = string.sub(promt,indx+2,#promt)
  -- p(cardlog)
  -- local _,pos = string.find(cardlog,"b>")
  -- local last,_ = string.find(cardlog,"</")
  -- pos = pos + 1
  -- last = last -1
end
singleOptiSkill["chunlao"] = function(self,skill,promt,cancelable,skillmes) --醇醪优化
  local player,room = self.player,self.player.room
  if promt == "#ty_ex__chunlao-cost" then
    local cards = LU:getPlayerCardNameIds(player,"h",{"slash"})
    if #cards.slash > 0 then
      return EnCodeByUseSkill(skill.name,cards.slash,{})
    end
    return ""
  elseif string.startsWith(promt,"#ty_ex__chunlao-invoke") and #player:getPile("ty_ex__chengpu_chun") > 0 then
    local tar = getPlayerIdByPromt(promt)
    if tar then
      tar = room:getPlayerById(tar)
      if LangAI.ISSAMECAMP(player,tar) then
        return EnCodeByUseSkill(skill.name,table.random(player:getPile("ty_ex__chengpu_chun"),1),{})
      end
    end
    return ""
  end
end
singleOptiSkill["longyin"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  local tar = room:getPlayerById(getPlayerIdByPromt(promt))
  if not tar or not LangAI.ISSAMECAMP(player,tar) then return "" end
  local hands = skillmes.include_equip and player:getCardIds{Player.Hand, Player.Equip} or player:getCardIds{Player.Hand}
  if #hands == 0 then return "" end
  local curdata = room.logic:getCurrentEvent().data
  if curdata and curdata[1] then
    if curdata[1].card and curdata[1].card.color == Card.Red then
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,1,room.current == player and discards_prio_jinks_t or discards_prio_slashs_t),{}) 
    end
    local cards = LU:getPlayerCardNameIds(tar,"h",{"slash"})
    if #cards.slash > 0 then
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,1,room.current == player and discards_prio_jinks_t or discards_prio_slashs_t),{}) 
    else
      local ptn = "slash"
      local slashskill = table.find(player.player_skills, function(s)
        return type(s.pattern) == "string" and string.find(s.pattern,ptn)
      end)
      if slashskill then
        return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,1,room.current == player and discards_prio_jinks_t or discards_prio_slashs_t),{}) 
      end
    end
  end
  return ""
end
singleOptiSkill["liejie"] = function(self,skill,promt,cancelable,skillmes) --烈杰优化
  local player,room = self.player,self.player.room
  local hands = player:getCardIds{Player.Hand, Player.Equip}
  if #hands == 0 then return "" end
  local target = room:getPlayerById(getPlayerIdByPromt(promt))
  local filtercolorcards = function(cards,color,exceptcardname)
    local importeuips = {Card.SubtypeArmor,Card.SubtypeTreasure,Card.SubtypeOffensiveRide} 
    return table.filter(cards,function(cid) 
      local card = Fk:getCardById(cid)
      if card.type == Card.TypeEquip and table.contains(importeuips,card.sub_type) and room:getCardArea(cid) == Card.PlayerEquip then return end
      return card.color == color and not table.contains(exceptcardname,card.trueName)
    end)
  end
  if target and string.startsWith(promt,"#liejie-cost") then
    if LangAI.ISSAMECAMP(player,target) then
      local blackcards = filtercolorcards(hands,Card.Black,{"peach","analeptic","ljsy","ex_nihilo"})
      local num = math.min(#blackcards,3)
      if num > 0 then
        return EnCodeByUseSkill(skill.name,getSelCardsSeq(blackcards,num,discards_prio_slashs_t),{})
      end
    else
      local redcards = filtercolorcards(hands,Card.Red,{"peach","analeptic","ljsy","ex_nihilo"})
      local num = math.min(#redcards,3)
      if 3 - num > 0 then
        local blackcards = filtercolorcards(hands,Card.Black,{"peach","analeptic","ljsy","ex_nihilo"})
        if #blackcards > 0 then
          local n = math.min(#blackcards,3 - num)
          table.insertTable(redcards,blackcards)
          return EnCodeByUseSkill(skill.name,getSelCardsSeq(redcards,num+n,discards_prio_slashs_t),{})
        end
        if num > 0 then
          return EnCodeByUseSkill(skill.name,getSelCardsSeq(redcards,num,discards_prio_slashs_t),{})
        end
      else
        return EnCodeByUseSkill(skill.name,getSelCardsSeq(redcards,num,discards_prio_slashs_t),{})
      end
    end
  else
    local blackcards = filtercolorcards(hands,Card.Black,{"peach","analeptic","ljsy","ex_nihilo"})
    local num = math.min(#blackcards,3)
    if num > 0 then
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(blackcards,num,discards_prio_slashs_t),{})
    end
  end
  return ""
end

singleOptiSkill["cuijin"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  local hands = skillmes.include_equip and player:getCardIds{Player.Hand, Player.Equip} or player:getCardIds{Player.Hand}
  if #hands == 0 then return "" end
  local tskill = Fk.skills[skillmes and skillmes.skillName]
  local id = getPlayerIdByPromt(promt)
  local target = room:getPlayerById(id)
  local curdata = room.logic:getCurrentEvent().data
  local toid = curdata and curdata[1] and curdata[1].tos[1][1]
  local totar = room:getPlayerById(toid)
  if target and totar then
    if LangAI.ISSAMECAMP(player,target) and not table.find(totar.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "jink" end) then
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,1,discards_prio_jinks_t),{})
    end
    if not LangAI.ISSAMECAMP(player,target) and table.find(totar.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "jink" end) then
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,1,discards_prio_jinks_t),{})
    end
  end
  return ""
end
singleOptiSkill["discard_skill"] = function(self,skill,promt,cancelable,skillmes)--弃牌逻辑优化
  local player,room = self.player,self.player.room
  local hands = player:getCardIds{Player.Hand}
  hands = table.filter(hands,function(cid) return not player:prohibitDiscard(Fk:getCardById(cid)) end)
  if #hands == 0 then return "" end
  if room.current == player and player.phase < Player.Discard then
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,skillmes.num,discards_prio_jinks_t),{})
  else
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,skillmes.num,discards_prio_slashs_t),{})
  end
end
singleOptiSkill["renxin"] = function(self,skill,promt,cancelable,skillmes) --仁心
  local player,room = self.player,self.player.room
  local equips = player:getCardIds("he")
  local ds_tar = room:getPlayerById(getPlayerIdByPromt(promt))
  equips= LangAI.patByCards(equips,skillmes.pattern,1)
  if not equips or not ds_tar or not LangAI.ISSAMECAMP(player,ds_tar) then return "" end

  local needpeachs = 0
  for _,pr in ipairs(room.alive_players) do
    if LangAI.ISSAMECAMP(player,pr) then
      local cards = LU:getPlayerCardNameIds(pr,"h",{"peach"})
      needpeachs = #cards.peach + needpeachs
    end
  end
  return needpeachs > 0 and "" or EnCodeByUseSkill(skill.name,equips,{})
end
singleOptiSkill["shanjia"] = function(self,skill,promt,cancelable,skillmes) --善甲
  local player,room = self.player,self.player.room
  local cards = player:getCardIds("he")
  local exp = Exppattern:Parse(".|.|.|.|.|equip")
  local equips,noequips = {},{}
  for _, cid in ipairs(cards) do
    local card = Fk:getCardById(cid)
    if exp:match(card) then 
      table.insert(equips,cid)
      if #equips == skillmes.num then return EnCodeByUseSkill(skill.name,equips,{}) end
    else
      table.insert(noequips,cid)
    end
  end
  local value = skillmes.num - #equips
  noequips = getSelCardsSeq(noequips,math.min(value,#noequips),discards_prio_jinks_t)
  for i=1,value do
    if #noequips >0 then
      table.insert(equips,table.remove(noequips,1))
    end
  end
  return EnCodeByUseSkill(skill.name,equips,{})
end
singleOptiSkill["#double_swords_skill"] = function(self,skill,promt,cancelable,skillmes) --雌雄双股剑
  local player,room = self.player,self.player.room
  local hands = player.player_cards[Player.Hand]
  local ds_tar = room:getPlayerById(getPlayerIdByPromt(promt))
  if ds_tar and LangAI.ISSAMECAMP(player,ds_tar) then return "" end
  if #hands == 1 then
    local alonecard = Fk:getCardById(hands[1])
    local importcards = {"peach","jink","analeptic"}
    if table.contains(importcards,alonecard.trueName) then
      return ""
    else
      return player.hp > 2 and "" or EnCodeByUseSkill(skill.name,{hands[1]},{})
    end 
  else
    if ds_tar then
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(table.clone(hands),1,discards_prio_slashs_t),{})
    end
    return ""
  end
end
singleOptiSkill["xiashu"] = function(self,skill,promt,cancelable,skillmes) --下书）
  local player,room = self.player,self.player.room
  if skill.name == "choose_cards_skill" and skillmes and skillmes.skillName == "xiashu" then
    local hands = player:getCardIds("h")
    if #hands > 0 then
      return EnCodeByUseSkill(skill.name,table.random(hands,math.floor(#hands/2)),{})
    end
  end
end
singleOptiSkill["zhenwei"] = function(self,skill,promt,cancelable,skillmes) --十周年镇卫）
  local player,room = self.player,self.player.room
  if skill.name == "discard_skill" and skillmes and skillmes.skillName == "ty_ex__zhenwei" then
    player.zhenwei_info = nil
    local logicdata = room.logic:getCurrentEvent().data[1]
    local card = logicdata and logicdata.card
    local cantrigskill
    if logicdata.from and card and logicdata.tos and logicdata.tos[1] then
      local to = room:getPlayerById(logicdata.tos[1][1])
      local from = room:getPlayerById(logicdata.from)
      if not LangAI.ISSAMECAMP(player,to) or (to.subhp and to.hp / to.maxHp > 0.4) then return "" end

      if card.trueName == "slash" then
        local toeffect = from:isCardEffectTo(to,card)
        local myeffect = from:isCardEffectTo(player,card)
        if not myeffect then 
          cantrigskill = true
          player.zhenwei_info = "ty_ex__zhenwei_transfer"
        end
        if toeffect and player:getCardOrSkillByPat("jink","he","prohibitUse") then
          cantrigskill = true
          player.zhenwei_info = "ty_ex__zhenwei_transfer"
        end
        if to.hp <= 3 and toeffect then
          cantrigskill = true
          player.zhenwei_info = "ty_ex__zhenwei_recycle"
        end
      elseif card.trueName == "dismantlement" or card.trueName == "snatch" or card.trueName == "indulgence" then
        cantrigskill = true
        player.zhenwei_info = "ty_ex__zhenwei_recycle" 
      elseif card.trueName == "duel" then
        local myslashs = table.filter(player.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName=="slash" end)
        local fromslashs = table.filter(from.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName=="slash" end)
        cantrigskill = true
        player.zhenwei_info = #myslashs > #fromslashs and "ty_ex__zhenwei_transfer" or "ty_ex__zhenwei_recycle"
      elseif card.trueName == "collateral" or card.trueName == "fire_attack" or card.trueName == "supply_shortage" then 
        cantrigskill = true
        player.zhenwei_info = "ty_ex__zhenwei_transfer" 
      end
    end
    if cantrigskill then
      local hands = player:getCardIds{Player.Hand, Player.Equip}
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,1,discards_prio_slashs_t),{})
    end
    return ""
  end
  if skill.name == "ty_ex__zhenwei" and skillmes and skillmes.choice then
    return player.zhenwei_info or "ty_ex__zhenwei_recycle"
  end
end
singleOptiSkill["danshou"] = function(self,skill,promt,cancelable,skillmes) --十周年胆守（dis_sel_cards技能里单独优化）
  local player,room = self.player,self.player.room
  local hands = player:getCardIds{Player.Hand, Player.Equip}
  local ds_tar = room.current
  -- print(promt.."=====弃牌时候胆守目标===="..ds_tar.general)
  if LangAI.ISSAMECAMP(player,ds_tar) then return "" end
  local tarhands = ds_tar.player_cards[Player.Hand]
  if #hands >= #tarhands then
    if #hands < 1.3 * #tarhands then return "" end
  else
    return ""
  end
end
--------dis_sel_cards技能通用处理（始）----------

--------------技能选项单独优化（始）-----------------
local luochong_selchc
singleOptiSkill["luochong"] = function(self,skill,promt,cancelable,skillmes) --有choose_players也有其他扩展包的luochong需要区分
  local player,room = self.player,self.player.room
  if not skillmes then return end
  if skill.name == "luochong" and skillmes.choice and #skillmes.choice ~= 0 then
    local choice = skillmes.choice
    if luochong_selchc and table.contains(choice,luochong_selchc) then return luochong_selchc end
    luochong_selchc = nil
    return
  end
  if skill.name == "choose_players_skill" and skillmes.skillName =="luochong" and skillmes.targets and #skillmes.targets>0 then
    local selret
    local filtarfunc = function(mark,enemy_friend,condi_func)
      if player:getMark(mark) == "0" then
        local findtar = table.find(room.alive_players,function(pr)
          if enemy_friend =="enemy" and not LangAI.ISSAMECAMP(player,pr) and pr:getMark("luochong-round") == 0 and condi_func(pr) then return true end
          if enemy_friend =="friend" and LangAI.ISSAMECAMP(player,pr) and pr:getMark("luochong-round") == 0 and condi_func(pr) then return true end
        end)
        if findtar then return {findtar.id,mark} end
      end
    end
    selret = filtarfunc("luochong2","enemy",function(pr) return pr.hp < 3 end) or filtarfunc("luochong1","friend",function(pr) return pr:getLostHp() > 0 and pr.hp < 3 end) or filtarfunc("luochong3","enemy",function(pr) return #pr.player_cards[Player.Equip] > 0 end) or filtarfunc("luochong4","friend",function(pr) return true end)
    if not selret then selret = filtarfunc("luochong2","enemy",function(pr) return true end) or filtarfunc("luochong1","friend",function(pr) return true end) or filtarfunc("luochong3","enemy",function(pr) return true end) end 
    if selret then
      luochong_selchc = selret[2]
      return EnCodeByUseSkill(skill.name,{},{selret[1]})
    end
  end
end
local prohiforeach
singleOptiSkill["#puyuanShop-choice"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  if not skillmes then return end
  for _,chs in ipairs(skillmes.choice) do
    if chs ~= "Exist" then 
      if prohiforeach and prohiforeach == chs then prohiforeach = nil return "Exist" end
      local pricepos,len = string.find(chs,":%d:") 
      local num
      if not pricepos then 
        local newpos = string.find(chs,"%d")  
        num = tonumber(string.sub(chs,newpos))
      else
        num = tonumber(string.sub(chs,len+1))
      end
      if not num then prohiforeach = nil return "Exist" end
      if player:getMark("@gold_num") >= num then prohiforeach = chs return chs end
    end
  end
  prohiforeach = nil
  return "Exist"
end
singleOptiSkill["yuandi"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  if not skillmes then return end
  local choice = skillmes.choice
  if #choice == 1 then return choice[1] end
  local data = room.logic:getCurrentEvent().parent.data[1]
  local tar = data and room:getPlayerById(data.from)
  if not tar then return choice[1] end 
  return LangAI.ISSAMECAMP(player,tar) and "yuandi_draw" or "yuandi_discard"
end
singleOptiSkill["benghuai"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  if not skillmes then return end
  local choice = skillmes.choice
  if #choice == 1 then return choice[1] end
  return player.hp == player.maxHp and "loseHp" or "loseMaxHp"
end
singleOptiSkill["kuanggu"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  if not skillmes then return end
  local choice = skillmes.choice
  if #choice == 1 then return choice[1] end
  local slash = Fk:cloneCard("slash")
  if player:canUse(slash) and not player:prohibitUse(slash) then
    return "draw1"
  end
  if player:isWounded() then
    return "recover"
  end
  return "draw1"
end
singleOptiSkill["benxi_choice"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  if not skillmes then return end
  local choice = skillmes.choice
  local data = room.logic:getCurrentEvent().parent.data[1]
  local usecard = data and data.card
  -- if not usecard then return {"ty_ex__benxi_choice3","ty_ex__benxi_choice4"} end --开发者可能后面会改多选
  if not usecard then return "ty_ex__benxi_choice4" end 
  local selfuse = usecard.skill:feasible({}, {}, player, card)
  if choice and #choice > 0 then
    local others = room:getOtherPlayers(player)
    local emys = LangAI.GetPlayersByCamp(player,others,LangAI.ISENEMY)
    if (usecard.is_damage_card or not selfuse) and #emys > 1 then 
      if table.contains(choice,"ty_ex__benxi_choice1") then return "ty_ex__benxi_choice1" end
      if usecard.is_damage_card and table.contains(choice,"ty_ex__benxi_choice4") then return "ty_ex__benxi_choice4" end
      if not usecard.is_damage_card and table.contains(choice,"ty_ex__benxi_choice3") then return "ty_ex__benxi_choice3" end
    end
    if selfuse and #LangAI.GetPlayersByCamp(player,others,LangAI.ISFRIEND) > 0 then
      if table.contains(choice,"ty_ex__benxi_choice1") then return "ty_ex__benxi_choice1" end
      if table.contains(choice,"ty_ex__benxi_choice3") then return "ty_ex__benxi_choice3" end
    end
    if usecard.trueName == "slash" then 
      local eid = emys[1]:getEquipment(Card.SubtypeArmor)
      local chs2 = table.contains(choice,"ty_ex__benxi_choice2") and "ty_ex__benxi_choice2"
      local chs3 = table.contains(choice,"ty_ex__benxi_choice3") and "ty_ex__benxi_choice3"
      local chs4 = table.contains(choice,"ty_ex__benxi_choice4") and "ty_ex__benxi_choice4"
      local chs34 = chs3 or chs4
      local chs23 = chs2 or chs3
      return (not eid and chs34) and chs34 or (player:isCardEffectTo(emys[1],usecard) and chs34 or chs23)
    end
    if table.contains(choice,"ty_ex__benxi_choice3") then return "ty_ex__benxi_choice3" end 
    if table.contains(choice,"ty_ex__benxi_choice4") then return "ty_ex__benxi_choice4" end
    -- return {"ty_ex__benxi_choice3","ty_ex__benxi_choice4"} 
  end
end
singleOptiSkill["pianchong"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  if not skillmes or not skillmes.choice then return end
  local choice = skillmes.choice
  if #choice == 1 then return choice[1] end
  local redcards,blackcards = 0,0
  for _,cid in ipairs(player.player_cards[Player.Hand]) do
    local card = Fk:getCardById(cid)
    if player:canUse(card) then
      if card.color == Card.Red then redcards = redcards+1 end
      if card.color == Card.Black then blackcards = blackcards+1 end
    end
  end
  return redcards >= blackcards and "red" or "black"
end
singleOptiSkill["shanshen"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  if not skillmes then return end
  local choice = skillmes.choice
  if #choice == 1 then return choice[1] end
  --"xianzhu2", "xianzhu3"
  local yuqimark= player:getMark("@yuqi")
  if yuqimark == 0 then yuqimark = {0,3,1,1} end
  local isyuqi1,isyuqi4,isyuqi2 = table.contains(choice,"yuqi1"),table.contains(choice,"yuqi4"),table.contains(choice,"yuqi2")
  if isyuqi1 and yuqimark[1] < 1 then return "yuqi1" end
  if isyuqi1 and yuqimark[2] > 3 and yuqimark[4] <= yuqimark[2] and yuqimark[1] <= 3 then return "yuqi1" end
  if isyuqi4 and yuqimark[4] < yuqimark[2] then return "yuqi4" end
  if isyuqi2 and yuqimark[4] >= yuqimark[2] then return "yuqi2" end
  if isyuqi1 then return "yuqi1" end
  if table.contains(choice,"yuqi3") then return "yuqi3" end
  return table.random(choice)
end
singleOptiSkill["xianjing"] = function(self,skill,promt,cancelable,skillmes)
  return singleOptiSkill["shanshen"](self,skill,promt,cancelable,skillmes)
end
singleOptiSkill["xianzhu"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  if not skillmes or not skillmes.choice then return end
  local choice = skillmes.choice
  if #choice == 1 then return choice[1] end
  --"xianzhu2", "xianzhu3"
  if table.contains(choice,"xianzhu1") then return "xianzhu1" end
  if table.contains(choice,"xianzhu3") and player:getMark("xianzhu3") <= 2 then return "xianzhu3" end
  if table.contains(choice,"xianzhu2") then return "xianzhu2" end
end
singleOptiSkill["yuyun"] = function(self,skill,promt,cancelable,skillmes)
  local player,room = self.player,self.player.room
  if not skillmes then return end
  local choice = skillmes.choice
  local skillName = skillmes.skillName
  if choice then
    if #choice <= 2 and choice[1] == "loseHp" then
      return player.maxHp / 2 < player.hp and "loseHp" or "loseMaxHp"
    end
    -- local selseqs = {"yuyun1", "yuyun2", "yuyun3", "yuyun4", "yuyun5", "Cancel"}
    if table.contains(choice,"yuyun2") then return "yuyun2" end
    if table.contains(choice,"yuyun5") then 
      local tars = LangAI.GetPlayersByCamp(player,room:getOtherPlayers(player, false),LangAI.ISFRIEND)
      if #tars > 0 then 
        table.sort(tars,function(a,b) return #a.player_cards[Player.Hand] < #b.player_cards[Player.Hand] end) 
        if #tars[1].player_cards[Player.Hand] < tars[1].maxHp then self.yuyun5 = tars[1].id return "yuyun5" end
      end 
    end
    if table.contains(choice,"yuyun4") then return "yuyun4" end
    if table.contains(choice,"yuyun1") then return "yuyun1" end
    if table.contains(choice,"yuyun3") then return "yuyun3" end
  end
  if skillName and promt then
    if string.startsWith(promt,"#yuyun2") or string.startsWith(promt,"#yuyun4") then 
      local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISENEMY)
      if #tars > 0 then table.sort(tars,function(a,b) return a.hp < b.hp end) return EnCodeByUseSkill(skillName,{},{tars[1].id}) end 
    end
    if string.startsWith(promt,"#yuyun5") and self.yuyun5 then 
      local selid = self.yuyun5
      self.yuyun5 = nil
      return EnCodeByUseSkill(skillName,{},{selid})
    end
  end
  return "Cancel"
end
singleOptiSkill["lingren"] = function(self,skill,promt,cancelable,skillmes) --凌人
  local player,room = self.player,self.player.room
  if skill.name == "choose_players_skill" then 
    local tars = LangAI.GetPlayersByCamp(player,skillmes.targets,LangAI.ISENEMY)
    table.sort(tars,function(a,b) 
      local cala = LU:calPlayerInfo(a,"jink")
      local calb = LU:calPlayerInfo(b,"jink")
      return cala < calb
    end)
    return EnCodeByUseSkill(skill.name,{},{tars[1].id})
  else
    local tar = room:getPlayerById(getPlayerIdByPromt(promt))
    if tar then
      local hands = tar:getCardIds("h")
      if #hands == 0 then
        return json.encode({})
      else
        local caltype = {}
        for _,cid in ipairs(hands) do
          local card = Fk:getCardById(cid)
          if card.type == Card.TypeBasic and not table.contains(caltype,"lingren_basic") then
            table.insert(caltype,"lingren_basic")
          end
          if card.type == Card.TypeTrick and not table.contains(caltype,"lingren_trick") then
            table.insert(caltype,"lingren_trick")
          end
          if card.type == Card.TypeEquip and not table.contains(caltype,"lingren_equip") then
            table.insert(caltype,"lingren_equip")
          end
        end
        return json.encode(caltype)
      end
    else
      return json.encode({})
    end
  end
  if not skillmes then return end
  
end
singleOptiSkill["xingchong"] = function(self,skill,promt,cancelable,skillmes) --幸宠
  local player,room = self.player,self.player.room
  if skill.name == "xingchong" and skillmes and skillmes.choice then
    local handnum = #player.player_cards[Player.Hand]
    if handnum >= player.maxHp then
      return "0"
    else
      return tostring(player.maxHp - handnum)
    end 
  end
  if skill.name == "choose_cards_skill" and skillmes then
    local hands = table.clone(player.player_cards[Player.Hand])
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(hands,skillmes.num,selcards_prio_t),{})
  end
end
singleOptiSkill["langmie"] = function(self,skill,promt,cancelable,skillmes) --狼灭
  local player,room = self.player,self.player.room
  if promt and string.startsWith(promt,"#langmie") then
    local discards = player:getCardIds("he")
    local tar = room.current
    if LangAI.ISSAMECAMP(player,tar)  then
      if promt[9] ~= "2" then
        return EnCodeByUseSkill(skill.name,getSelCardsSeq(discards,1,discards_prio_slashs_t),{})
      end
    else
      if promt[9] == "3" then
        player.langmie_dmgemy = true
      end
      return EnCodeByUseSkill(skill.name,getSelCardsSeq(discards,1,discards_prio_slashs_t),{})
    end
    return ""
  end
  if skillmes and skillmes.choice then
    if player.langmie_dmgemy then
      player.langmie_dmgemy = nil
      return "langmie_damage"
    else
      return "draw2"
    end 
  end
end
singleOptiSkill["yinghun"] = function(self,skill,promt,cancelable,skillmes) --英魂
  local player,room = self.player,self.player.room
  if promt and string.startsWith(promt,"#yinghun-choose") then
    local losehp = player:getLostHp()
    if losehp > 1 then
      local friends,enemys = {},{}
      for _,pr in ipairs(room:getOtherPlayers(player)) do
        if LangAI.ISSAMECAMP(player,pr) then      
          table.insert(friends,pr)
        else
          table.insert(enemys,pr)
        end
      end
      if #enemys == 1 and #enemys[1].player_cards[Player.Hand] + #enemys[1].player_cards[Player.Equip] == losehp then
        player.yinghunseltar = enemys[1].id 
        return EnCodeByUseSkill(skill.name,{},{enemys[1].id}) 
      else
        local jinkname = "jink"
        table.sort(friends,function (a,b) 
          local aret = LU:calPlayerInfo(a,jinkname)
          local bret = LU:calPlayerInfo(b,jinkname)
          return aret < bret
        end)
        player.yinghunseltar = friends[1].id 
        return EnCodeByUseSkill(skill.name,{},{friends[1].id}) 
      end
    else
      for _,pr in ipairs(room:getOtherPlayers(player)) do
        if LangAI.ISSAMECAMP(player,pr) then      
          player.yinghunseltar = pr.id    
          return EnCodeByUseSkill(skill.name,{},{pr.id}) 
        end
      end
    end
  end
  if promt and string.startsWith(promt,"#AskForDiscard") and skillmes and skillmes.num then
    return EnCodeByUseSkill(skill.name,getSelCardsSeq(player:getCardIds("he"),skillmes.num,discards_prio_slashs_t),{})
  end
  if skillmes and skillmes.choice then
    local choice = skillmes.choice
    -- local tar = room.logic:getCurrentEvent().data[4].tos[1]
    tar = room:getPlayerById(player.yinghunseltar)
    if tar then
      player.yinghunseltar = nil
      return LangAI.ISSAMECAMP(player,tar) and choice[1] or choice[2]
    end
  end
end
--------------技能选项单独优化（末）-----------------

--------------唤醒其他技能单独优化（始）-----------------
singleOptiSkill["virtual_viewas"] = function(self,skill) --平襄
  local player,room = self.player,self.player.room
  local tars = table.filter(room:getOtherPlayers(player),function (pr)
    if not LangAI.ISSAMECAMP(player,pr) then return true end
  end)
  if #tars == 0 then return "" end
  table.sort(tars,function(a,b) return a.hp < b.hp end)
  tars = table.map(tars,Util.IdMapper)
  return EnCodeByUseSkill(skill.name,{},{tars[1]})
end
singleOptiSkill["realcard_viewas"] = function(self,skill,promt,cancelable,data) --泛音
  if not data.optional_cards or #data.optional_cards == 0 then return "" end
  local player,room = self.player,self.player.room
  -- if skill.interaction then skill:interaction() end
  local usecard = skill:viewAs(data.optional_cards)
  if not usecard then return "" end
  if usecard.type == Card.TypeEquip and player:getEquipment(usecard.sub_type) then return "" end

  local seltars = LangAI.UseCardLogicBySkill(self,usecard)
  if seltars then return EnCodeByUseSkill(skill.name,data.optional_cards,seltars) end
  return ""
end
singleOptiSkill["suji_viewas"] = function(self,skill) --肃疾
  local player,room = self.player,self.player.room
  local blackcard = table.find(player:getCardIds("he"),function(cid) return Fk:getCardById(cid).color == Card.Black end)
  local seltars = not LangAI.ISSAMECAMP(player,room.current) and {room.current.id} or nil
  if seltars and blackcard then return EnCodeByUseSkill(skill.name,{blackcard},seltars) end
  return ""
end
singleOptiSkill["qinguo_viewas"] = function(self,skill) --勤国
  local player,room = self.player,self.player.room
  if skill.interaction then skill:interaction() end
  local usecard = skill:viewAs()
  local seltars = usecard and LangAI.UseCardLogic[usecard.trueName](self,usecard)
  if seltars then return EnCodeByUseSkill(skill.name,{},seltars) end
  return ""
end
singleOptiSkill["siege_engine_slash"] = function(self,skill) --大公车出牌阶段用杀
  local player,room = self.player,self.player.room
  if skill.interaction then skill:interaction() end
  local usecard = skill:viewAs()
  local seltars = usecard and LangAI.UseCardLogic[usecard.trueName](self,usecard)
  if seltars then return EnCodeByUseSkill(skill.name,{},seltars) end
  return ""
end
singleOptiSkill["zhiyi_viewas"] = function(self,skill) --执义用杀
  local player,room = self.player,self.player.room
  if skill.interaction then skill:interaction() end
  local usecard = skill:viewAs()
  local seltars = usecard and LangAI.UseCardLogic[usecard.trueName](self,usecard)
  if seltars then return EnCodeByUseSkill(skill.name,{},seltars) end
  return ""
end
singleOptiSkill["spear_skill"] = function(self,skill,promt) --丈八蛇矛
  local player,room = self.player,self.player.room
  local hands = table.map(player.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid) end) 
  if #hands < 2 or table.filter(hands,function(cd) return cd.trueName == "slash" end) then return end
  local importcards = {peach=true,analeptic=true}
  local sortcards = table.filter(hands,function(cd) return not importcards[cd.trueName] end)
  if #sortcards > 1 then
    sortcards = table.random(sortcards,2)
    local usecard = skill:viewAs(sortcards)
    if not usecard or not player:canUse(usecard) then return end
    player.isplaying = nil
    local ret = LangAI.UseCardLogic[usecard.trueName](self,usecard)
    if ret then
      return not promt and EnCodeByUseSkill(skill.name,sortcards,ret) or {trueName = "slash",skillname = skill.name,selected_cards = sortcards,selected_targets = ret}
    end
  end
end
singleOptiSkill["jungong"] = function(self,skill,promt,cancelable,skillmes)  --峻攻优化(视为技能。有可选项,选牌和选人)
  local player,room = self.player,self.player.room
  local interaction = Fk.skills["jungong"]:interaction()
  if #interaction.choices == 0 then return end
  local usedTimes = player:usedSkillTimes(self.name) + 1
  if player:getMark("jungong_nullified-turn") ~= 0 or player.hp <= 0 or #player:getCardIds({ Player.Hand, Player.Equip }) < usedTimes then return end
  local hands = player.player_cards[Player.Hand]
  if #hands >= usedTimes then
    skill.interaction.data = interaction.choices[1]
    local selcards = getSelCardsSeq(table.clone(hands),usedTimes,discards_prio_jinks_t)
    local usecard = skill:viewAs(selcards)
    local seltars = usecard and LangAI.UseCardLogic[usecard.trueName](self,usecard)
    if seltars and #seltars > 0 then
      return EnCodeByUseSkill(skill.name,selcards,seltars,skill.interaction.data) 
    end
  else
    if player.hp > 1 + usedTimes then
      skill.interaction.data = interaction.choices[2]
      local usecard = skill:viewAs({})
      local seltars = usecard and LangAI.UseCardLogic[usecard.trueName](self,usecard)
      if seltars and #seltars > 0 then
        return EnCodeByUseSkill(skill.name,{},seltars,skill.interaction.data) 
      end
    end
  end
end
-- singleOptiSkill["ty_ex__zhuhai_active"] = function(self,skill) --诛害用杀
--   local player,room = self.player,self.player.room
--   if skill.interaction then 
--     self.interaction.data = table.random(skill:interaction())
--   end
--   local usecard = skill:viewAs()
--   local seltars = usecard and LangAI.UseCardLogic[usecard.trueName](self,usecard)
--   if seltars then return EnCodeByUseSkill(skill.name,{},seltars) end
--   return ""
-- end
singleOptiSkill["chouce"] = function(self,skill,promt,cancelable,skillmes) --筹策
  local player,room = self.player,self.player.room
  local prompt = promt
  local t
  if prompt == "#chouce-draw" then
    t = player:getMark("xianfu")
    t = (type(t) == "table" and t[1] and t[1][1] and LangAI.ISSAMECAMP(player,room:getPlayerById(t[1][1]))) and {t[1][1]} or {player.id}
  else
    t = prioDismanFriArea(player)
    if t then
      t = {t[1]}
    else
      local filtertars = table.filter(room.alive_players,function(pr)
        if not LangAI.ISSAMECAMP(player,pr) and #pr:getCardIds("he") > 0 then
          return true
        end
      end)
      if #filtertars == 0 then return "" end
      table.sort(filtertars,function (a,b) 
        local aret = LangAI.sortSelEquips(a) 
        local bret = LangAI.sortSelEquips(b) 
        if aret + bret ~= 0 then
          return aret > bret
        else
          return a.hp < b.hp
        end 
      end)
      t = {filtertars[1].id}
    end
  end
  if t then return EnCodeByUseSkill(skill.name,{},t) end
  return ""
end

-- singleOptiSkill["aocai"] = function(self,skill,promt,cancelable,skillmes)--傲才
--   local player,room = self.player,self.player.room
--   local hands = player.special_cards["aocai"] 
--   if #hands == 0 then return end
--   local cid = table.find(hands,function(cid)
--     local c = Fk:getCardById(cid)
--     return not player:prohibitUse(c)
--   end)
--   local setars = skillmes.must_targets or (skillmes.exclusive_targets and skillmes.exclusive_targets[1] and {skillmes.exclusive_targets[1]}) or {}
--   if cid then return EnCodeByUseSkill(skill.name,{cid},setars) end
--   return
-- end
--
--------------唤醒其他技能单独优化（末）-----------------

--发动其他技能
local useSkillNames = {discard_skill = true,choose_cards_skill = true,distribution_skill=true}
random_cb.AskForUseActiveSkill = function(self, jsonData)
  local player = self.player
  local room = player.room
  local data = json.decode(jsonData)
  local skill = Fk.skills[data[1]]
  local promt = data[2]
  local cancelable = data[3]
  local skillmes = data[4]
  if (skill and LangAI.BLACKSKILLS[skill.trueName]) or (skillmes and LangAI.BLACKSKILLS[skillmes.skillName]) then
    return ""
  end
  if cancelable and LangAI.CANCELSELCARD[data[1]] then
    return ""
  end
  if skillmes and promt and string.find(promt,"#askForPindian") then --优先优化拼点
    return singleOptiSkill["askforPinDian"](self,skill,promt,cancelable,skillmes)
  end
  if skill and useSkillNames[skill.trueName] and skillmes then --选择或弃自己牌的技能另外作处理askforcard
    local skilltrue = skillmes and skillmes.skillName and Fk.skills[skillmes.skillName] and Fk.skills[skillmes.skillName].trueName
    local skillfunc = singleOptiSkill[skilltrue]
    local result = skillfunc and skillfunc(self,skill,promt,cancelable,skillmes) or nil --单独优化其他技能discard_skill/choose_cards_skill
    if result then return result end
    return singleOptiSkill["dis_sel_cards"](self,skill,promt,cancelable,skillmes)  --没有的再用discard_skill/choose_cards_skill
  end
  if skill then 
    if skill.trueName == "choose_players_skill" then --选择其他角色技能另外作处理
      local skilltrue = skillmes and skillmes.skillName and Fk.skills[skillmes.skillName] and Fk.skills[skillmes.skillName].trueName
      local skillfunc = singleOptiSkill[skilltrue]
      local result = skillfunc and skillfunc(self,skill,promt,cancelable,skillmes) or nil --单独优化其他技能chooseplayers
      if result then return result end
      local ret = singleOptiSkill[skill.trueName](self,skill,promt,cancelable,skillmes)  --没有的再用chooseplayers
      if ret then return ret end
    else
      local skillfunc = singleOptiSkill[skill.trueName] --使用其他技能。比如勤国，平襄，筹测内嵌的其他技能
      return skillfunc and skillfunc(self,skill,promt,cancelable,skillmes)
    end
  end
  if not skill.feasible then return "" end
  for k, v in pairs(skillmes) do
    skill[k] = v
  end
  local ret = useActiveSkill(self, skill)
  if ret then return ret end
  return ""
end

--对选项内容进行处理
local filterChoices = function(choice,selcont)
  return table.find(choice,function(content) 
    if string.find(content,selcont) then 
      return true 
    end 
  end)
end
--多选项功能
random_cb.AskForChoices = function(self, jsonData)
  --改为随机选项
  local player = self.player
  local room = player.room
  local data = json.decode(jsonData)
  local choice = data[1]
  local skillname = data[5]
  local cancelable = data[4]
  local prompt = data[6]
  local skill = Fk.skills[skillname]
  if skill and LangAI.BLACKSKILLS[skill.trueName] then
    return json.encode({})
  end
  if skill and singleOptiSkill[skill.trueName] then
    local ret= singleOptiSkill[skill.trueName](self,skill,prompt,cancelable,{choice = choice})
    if ret then return ret end
  end
  return json.encode({})
end
--选项功能
random_cb.AskForChoice = function(self, jsonData)
  --改为随机选项
  local player = self.player
  local room = player.room
  local data = json.decode(jsonData)
  -- p(data)
  local choice = data[1]
  local skillname = data[3]
  local skill = Fk.skills[skillname]
  if skill and LangAI.BLACKSKILLS[skill.trueName] then
    return ""
  end
  if type(choice) == "table" and #choice > 0 then
    if skillname == "#puyuanShop-choice" then
      local ret= singleOptiSkill["#puyuanShop-choice"](self,skill,nil,nil,{choice = choice})
      if ret then return ret end
    end
    if skill and singleOptiSkill[skill.trueName] then
      local ret= singleOptiSkill[skill.trueName](self,skill,nil,nil,{choice = choice})
      if ret then return ret end
    end
    if skillname and type(skillname) == "string" and skill and LangAI.SKILLCHOICE[skill.name] then
      local tarmes = data[4]
      local tarcont = LangAI.SKILLCHOICE[skill.name]
      if tarcont.mustnotchose then
        table.removeOne(choice,tarcont.mustnotchose)
        return table.random(choice)
      end
      if tarcont.mustchose then
        local chc = filterChoices(choice,tarcont.mustchose)
        if chc then return chc end
      end
      local id = getPlayerIdByPromt(tarmes)
      if #tarmes == 0 or not id then id = room.current.id end
      local target = room:getPlayerById(id)
      if target then
        if tarcont.tar == "friend" then
          if LangAI.ISSAMECAMP(player,target) then
            local chc = filterChoices(choice,tarcont.chose)
            if chc then return chc end
          end
        elseif tarcont.tar == "enemy" then
          if not LangAI.ISSAMECAMP(player,target) then
            local chc = filterChoices(choice,tarcont.chose)
            if chc then return chc end
          end
        else
          if LangAI.ISSAMECAMP(player,target) then
            if tarcont.chose.friend then
              local chc = filterChoices(choice,tarcont.chose.friend)
              if chc then return chc end
            end
          else
            if tarcont.chose.enemy then
              local chc = filterChoices(choice,tarcont.chose.enemy)
              if chc then return chc end
            end
          end
        end
      end
    end
    local randi = math.floor(math.random(1,#choice)+0.5) 
    local rand = choice[randi]
    return rand and rand or ""
  end
  return ""
end

local invokeBySpec = {}
invokeBySpec["zhenlie"] = function (player) --贞烈
  local room = player.room
  local data = room.logic:getCurrentEvent().data
  if not data[1] or not data[1].card then return "" end
  data = data[1]
  local from = data.from
  local tar = room:getPlayerById(from)
  if not tar then return "" end
  if LangAI.ISSAMECAMP(player,tar) then return "" end
  if player.hp > 1 then 
    if data.card.is_damage_card then return "1" end
    if data.card:isCommonTrick() and not data.card.multiple_targets and player.hp > 2 then return "1" end
  else
    if data.card.is_damage_card then
      if #player.player_cards[Player.Hand] == 0 then
        if player:hasSkill("#vine_skill") then
          local noeffectcards = {"slash","savage_assault","archery_attack"}
          return table.contains(noeffectcards,data.card.name) and "" or "1"
        elseif player:hasSkill("#nioh_shield_skill") and data.card.trueName == "slash" then
          return data.card.color == Card.Black and "" or "1"
        end
        return "1"
      else
        local cards = LU:getPlayerCardNameIds(player,"h",{"peach","analeptic"})
        if #cards.peach + #cards.analeptic > 0 then
          return "1"
        end
        local resolutions = {slash = "jink",archery_attack = "jink",duel = "slash",savage_assault="slash"}
        if resolutions[data.card.trueName] then
          local exp = Exppattern:Parse(resolutions[data.card.trueName])
          local respond = table.find(player.player_cards[Player.Hand],function(cid)
            if exp:match(Fk:getCardById(cid)) then return true end
          end)
          return respond and "" or "1"
        end
      end
    else
      return ""
    end
  end
  return ""
end
invokeBySpec["l_kuixi"] = function (player) --窥喜
  local room = player.room
  if #player.player_cards[Player.Hand] < 4 then return "1" end
  return ""
end
invokeBySpec["dulie"] = function (player,data) --谋dulie
  local room = player.room
  local card = room.logic:getCurrentEvent().data[1].card
  local atkrange = player:getAttackRange()
  if atkrange > 1 and player.hp > 2 and not card.is_damage_card then return "1" end
  if card.is_damage_card then
    return player.hp <= 2 and "" or "1"
  else
    return atkrange <= 1 and "" or "1"
  end
end
invokeBySpec["yuanzi"] = function (player,data) --援资
  local room = player.room
  if string.startsWith(data[2],"#yuanzi-give") then
    local pid = getPlayerIdByPromt(data[2])
    local tar = room:getPlayerById(pid)
    if tar and LangAI.ISSAMECAMP(player,tar) then
      return "1"
    else
      return ""
    end
  else
    return "1"
  end
end
invokeBySpec["lihuo"] = function (player,data) --十周年界恩怨
  local room = player.room
  if not data[2] then return "" end
  if string.startsWith(data[2],"#ty_ex__lihuo1") then
    local hasotheremy
    local fireslash = Fk:cloneCard("fire__slash")
    local emys = 0
    for _, pr in ipairs(room.alive_players) do
      if not LangAI.ISSAMECAMP(player,pr) and player:inMyAttackRange(pr) then 
        emys = emys + 1
      end
    end
    return emys > 1 and "1" or ""
  else
    return "1"
  end
end
invokeBySpec["xibing"] = function (player,data) --息兵
  local room = player.room
  local mes = data[2]
  local id = getPlayerIdByPromt(mes)
  local target = room:getPlayerById(id)
  if not target then return "" end
  local tarcards = target.player_cards[Player.Hand]
  if LangAI.ISSAMECAMP(player,target) then
    local conditioncards,canusecards = 0,0
    for _,cid in ipairs(tarcards) do
      local card = Fk:getCardById(cid)
      if target:canUse(card) then
        canusecards = canusecards + 1
        if card.color == Card.Black and not card.multiple_targets then
          conditioncards = conditioncards + 1
        end
      end
    end
    if canusecards == 0 then
      return "1"
    else
      if conditioncards == 0 then
        return canusecards == 1 and "1" or ""
      else
        return ""
      end   
    end
  else
    local status_skills = room.status_skills[TargetModSkill] or Util.DummyTable
    local slash = Fk:cloneCard("slash")
    local canmutyslash
    for _, skill in ipairs(status_skills) do
      if skill:bypassTimesCheck(target, slash.skill, Player.HistoryPhase, slash) then 
        canmutyslash = true
        break
      end
    end
    if (canmutyslash and #table.filter(tarcards,function(cid) return Fk:getCardById(cid).trueName == "slash" end) > 1) or (target.hp - #tarcards == 1) then
      return "1"
    else
      return ""
    end
  end
end
invokeBySpec["zhangjiq"] = function (player,data) --长姬
  local room = player.room
  local mes = data[2]
  local id = getPlayerIdByPromt(mes)
  local target = room:getPlayerById(id)
  if not target then return "1" end
  if LangAI.ISSAMECAMP(player,target) then
    return string.startsWith(mes,"#zhangji-discard") and "" or "1"
  else
    return string.startsWith(mes,"#zhangji-discard") and "1" or ""
  end
end
invokeBySpec["enyuan"] = function (player,data) --十周年界恩怨
  local room = player.room
  local mes = data[2]
  local id = getPlayerIdByPromt(mes)
  local target = room:getPlayerById(id)
  if not target then return "1" end
  if string.startsWith(mes,"#ty_ex__enyuan-en") then
    return LangAI.ISSAMECAMP(player,target) and "1" or ""
  else
    return not LangAI.ISSAMECAMP(player,target) and "1" or ""
  end
end
invokeBySpec["yuguan"] = function(player,data) --御关
  local room = player.room
  local pos = string.find(data[2],":%d") + 1
  local n = string.sub(data[2],pos)
  n = tonumber(n)
  if n == 0 then
    return ""
  else
    -- if ((player.maxHp -1) - player.hp) == 0 then return "" end
    if table.find(room.alive_players,function(pr) return LangAI.ISSAMECAMP(player,pr) and #pr.player_cards[Player.Hand] - pr.maxHp < -1 end) then return "1" end
    return ""
  end
end
invokeBySpec["miji"] = function(player,data) --秘计
  if data[2] then
    return #LangAI.GetPlayersByCamp(player,player.room:getOtherPlayers(player),LangAI.ISFRIEND) > 0 and "1" or ""
  else
    return "1"
  end 
end
invokeBySpec["fenji"] = function(player,data) --奋激
  local room = player.room
  local mes = data[2]
  local ds_tar = room:getPlayerById(getPlayerIdByPromt(mes))
  if not ds_tar or not LangAI.ISSAMECAMP(player,ds_tar) then return "" end
  return "1"
end
invokeBySpec["danshou"] = function (player,data) --十周年界胆守
  local room = player.room
  local mes = data[2]
  if string.startsWith(mes,"#ty_ex__danshou-draw") then --摸牌
    return getPlayerIdByPromt(mes) > 1 and "1" or ""
  else  --0牌直伤害
    local target = room.current
    print(mes.."=====询问时候胆守目标===="..target.general)
    return LangAI.ISSAMECAMP(player,target) and "" or "1"
  end
end
invokeBySpec["#ice_sword_skill"] = function (player) --寒冰剑
  local room = player.room
  local current = room.logic:getCurrentEvent()
  local e = current:findParent(GameEvent.CardEffect,Self)
  if not e then return "" end
  local cardeff = e.data and e.data[1] or nil
  if not cardeff then return "" end
  local target = room:getPlayerById(cardeff.to)
  if target.hp <= target.maxHp / 2 then return "" end
  if target:getEquipment(Card.SubtypeTreasure) or target:getEquipment(Card.SubtypeArmor) then
    return "1"
  else
    if target:getEquipment(Card.SubtypeDefensiveRide) and player:distanceTo(target) ~= 1 then
      return "1"
    else
      return ""
    end
  end
end
invokeBySpec["fenli"] = function (player,data) --奋厉
  local mes = data[2]
  local room = player.room
  local enemys = {}
  -- local is_maxhands = true
  local is_maxequipnum = true
  local is_maxhp = true
  for _,pr in ipairs(room.alive_players) do
    if not LangAI.ISSAMECAMP(player,pr) then table.insert(enemys,pr) end
    if player ~= pr then
      -- if #pr.player_cards[Player.Hand] > #player.player_cards[Player.Hand] then is_maxhands = false end
      if #pr.player_cards[Player.Equip] > #player.player_cards[Player.Equip] then is_maxequipnum = false end
      if pr.hp > player.hp then is_maxhp = false end
    end
  end
  if string.find(mes,"phase_draw") then
    if #enemys >= 2 and is_maxequipnum then
      return "1"
    end
    if #enemys == 1 and not is_maxequipnum then
      return "1"
    end
  end 
  if string.find(mes,"phase_play") then
    local n = 0
    for _, phase in ipairs({Player.Start, Player.Judge, Player.Draw}) do
      if player.skipped_phases[phase] then
        n = n + 1
      end
    end
    if n > 0 then return "" end
    local canusecards = 0
    local calone_slash = false
    for _,cid in ipairs(player.player_cards[Player.Hand]) do
      local card = Fk:getCardById(cid)
      if player:canUse(card) then
        if card.type == Card.TypeEquip and not player:getEquipment(card.sub_type) then canusecards = canusecards + 1 end 
        if card.type == Card.TypeTrick then canusecards = canusecards + 1 end
        if card.type == Card.TypeBasic then
          if card.trueName == "slash" and not calone_slash then canusecards = canusecards + 1 calone_slash = true end
          canusecards = canusecards + 1
        end 
      end
    end
    return canusecards > 1 and "" or "1"
  end
  if string.find(mes,"phase_discard") then
    return "1"
  end 
  return ""
end

function LangAI:friFoeByCard(skilltar,isjudge,sendata)
  local player = self.player
  local room = player.room
  local current = room.logic:getCurrentEvent()
  -- local e = current:findParent(GameEvent.CardEffect,Self)
  if not current.data or #current.data == 0 then return "" end
  -- local cardeff = e.data and e.data[1] or nil
  local data = current.data[1]
  local evevntype = current.event
  local target,restarget
  if type(data) == "function" then
    return "1"
  end
  if sendata and type(sendata) == "table" and sendata[2] and type(sendata[2]) == "string" then
    target = room:getPlayerById(getPlayerIdByPromt(sendata[2]))
  end
  if not target then
    if data.to then --一般是受到伤害时候
      target = type(data.to) == "number" and room:getPlayerById(data.to) or data.to 
    elseif data.who then
      target = type(data.who) == "number" and room:getPlayerById(data.who) or data.who
    end
  end
  if not target and data.tos and #data.tos > 0 then  --一般是即将成为目标时候
    -- local tids = AimGroup:getAllTargets(data.tos)
    local tids = data.tos
    if #tids == 1 then
      target = room:getPlayerById(tids[1][1])
    else
      if isjudge then
        local tid = table.find(tids,function (pid)
          if pid[1] == player.id then
            return true
          end
        end)
        if tid then
          target = room:getPlayerById(tid[1])
        end
      end
    end
  end
  if not target then return "" end
  if isjudge and data.from then
    restarget = type(data.from) == "number" and room:getPlayerById(data.from) or data.from
  end
  if LangAI.ISSAMECAMP(player,target) and skilltar == "friend" then 
    if isjudge and restarget and not restarget.dead then
      if LangAI.ISSAMECAMP(player,restarget) then
        return ""
      else
        return "1"
      end
    end
    return "1"
  end
  if not LangAI.ISSAMECAMP(player,target) and skilltar == "enemy" then
    return "1"
  end
  return ""
end

function LangAI:invokeSkillByType(typemes,name,data)
  local type = typemes.type
  local skilltar = typemes.skilltar
  local isjudege = typemes.isjudge
  if type == LangAI.INVOKENORMAL then
    return self:friFoeByCard(skilltar,isjudege,data)
  elseif type == LangAI.INVOKESPECIAL then
    local handle = invokeBySpec[name]
    if handle then
      return handle(self.player,data)
    else
      return ""
    end
  end
  return ""
end

function LangAI:invokeSkill(name,data)
  local typemes = LangAI.INVOKESKILL[name]
  if typemes then
    local result = self:invokeSkillByType(typemes,name,data)
    return result
  else
    return "1"
  end
end

--询问技能发动
random_cb.AskForSkillInvoke = function(self, jsonData)
  local data = json.decode(jsonData)
  local skill = Fk.skills[data[1]]
  if skill and LangAI.BLACKSKILLS[skill.trueName] then
    return ""
  end
  local invoFunc = skill and self:invokeSkill(skill.trueName,data) or ""
  return invoFunc
end

local handleEncode = function (data,isview)
  if isview then
    return json.encode{
      card = json.encode{
        skill = data.skillname,
        subcards = data.selected_cards,
      },
      targets = data.targets and data.targets or {},
      interaction_data = data.interaction_data and data.interaction_data or nil
    }
  end
  return json.encode{card = data.card,targets = data.targets and data.targets or {}} 
end

local nulliwhite_t = {ex_nihilo=true,god_salvation=true,amazing_grace=true,ljsy=true}
local dmgCards_t = {savage_assault="slash|.|.|.|.|.|.|",archery_attack="jink|.|.|.|.|.|.|",fire_attack="."}
local dmgCardToFriendNoNulli = function(cardname,from,to)
  local hpstatus = to.hp / to.maxHp
  if dmgCards_t[cardname] then
    if hpstatus > 0.5 then
      return true 
    else
      if cardname == "savage_assault" or cardname == "archery_attack" then
        local ret = to:getCardOrSkillByPat(dmgCards_t[cardname],Player.Hand,"prohibitResponse") 
        return ret or false 
      elseif cardname == "fire_attack" then
        return to.hp ~= 1
      end
    end
  elseif cardname == "duel" then
    if not from then return false end
    local toslashs = #table.filter(to.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)
    local fromslashs = #table.filter(from.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)
    return toslashs > fromslashs and true or (hpstatus > 0.5)
  end
end
--濒死对队友使用桃
local askforPeachHandle = function (usemes,card,player,isviewas,peachnum)
  local room = player.room
  if string.find(usemes,"#AskForPeaches:") then
    local one = string.find(usemes,":",1)
    local last = string.find(usemes,":",one+1)
    local id = string.sub(usemes,one+1,last-1)
    local idnumber = tonumber(id)
    local tar = room:getPlayerById(idnumber)
    if tar and not LangAI.ISSAMECAMP(player,tar) then
      return ""
    else
      local needpeachnum = string.sub(usemes,last+2)
      needpeachnum = tonumber(needpeachnum)
      if peachnum >= needpeachnum then
        local data = not isviewas and {card = card} or card
        return handleEncode(data,isviewas)
      else
        local friendspeachs = peachnum
        for _,pr in ipairs(room.alive_players) do
          if pr ~= player and LangAI.ISSAMECAMP(player,pr) then
            local needcardnames = {"peach"}
            if pr == tar then table.insert(needcardnames,"analeptic") end
            local cards = LU:getPlayerCardNameIds(pr,"h",needcardnames)
            friendspeachs = friendspeachs + #cards.peach + (cards.analeptic and #cards.analeptic or 0)
          end
        end
        local data = not isviewas and {card = card} or card
        return friendspeachs >= needpeachnum and handleEncode(data,isviewas) or ""
      end
    end
  elseif string.find(usemes,"#AskForPeachesSelf") then
    local data = not isviewas and {card = card} or card
    return handleEncode(data,isviewas)
  end
end

--使用无懈可击
local askforNulliHandle = function (target,trick_card,card,num,player,isviewas,usefrom)
  local room = player.room
  local trick,tar = trick_card,target
  local hands,judeges = player.player_cards[Player.Hand],player.player_cards[Player.Judge]
  local nullinum,isindul = num,false
  if #judeges > 0 then
    isindul = player:hasDelayTrueTrick("indulgence")
    if nullinum == 1 and isindul then  --1个无懈且被乐了会优先保留
      if room.current.id ~= player.id then 
        local trickcard = Fk:cloneCard(trick)
        if not trickcard.is_damage_card then 
          if not trickcard.multiple_targets and #hands == 1 and #player.player_cards[Player.Equip] == 0 and trick ~= "collateral" then --先判断是否只有手里一个无懈
            return handleEncode(not isviewas and {card = card} or card,isviewas)
          end
          return ""
        else
          return dmgCardToFriendNoNulli(trick,usefrom,tar) and "" or handleEncode(not isviewas and {card = card} or card,isviewas)
        end
      else
        if trick == "lightning" then return "" end
        if isindul and trick ~= "indulgence" and nullinum == 1 then --对于判定区多个锦囊牌且只有1个无邪则只对乐无邪
          return ""
        end
        local data = not isviewas and {card = card} or card
        return handleEncode(data,isviewas)
      end
    end
  end
  if nulliwhite_t[trick] then  --对自己或者队友使用增益的卡牌不打无懈
    if LangAI.ISSAMECAMP(player,tar) then
      return ""
    else
      if (trick == "god_salvation" or (trick == "ljsy" and tar ~= usefrom)) and tar.hp / tar.maxHp > 0.5 and tar.hp > 2 then
        return ""
      end
      local data = not isviewas and {card = card} or card
      return handleEncode(data,isviewas)
    end
  else
    if LangAI.ISSAMECAMP(player,tar) then  --对自己或者队友伤害锦囊打无懈看情况
      if nullinum == 1 and dmgCardToFriendNoNulli(trick,usefrom,tar) then --一个无懈情况，根据伤害锦囊锦囊牌响应手牌或技能来判断是否使用无懈
        return ""
      else
        if trick == "lightning" then 
          return "" 
        elseif trick == "dismantlement" and nullinum < 3 then 
          local tarhands = #tar.player_cards[Player.Hand]
          local hasequip = tar:getEquipment(Card.SubtypeDefensiveRide) or tar:getEquipment(Card.SubtypeArmor) or tar:getEquipment(Card.SubtypeWeapon)
          local nousenull = hasequip or (tar.hp / tar.maxHp <= 0.5 and tarhands < tar.hp)
          if not nousenull then
            return ""
          end
        elseif trick == "iron_chain" and (tar.hp > 2 or tar:getCardOrSkillByPat("jink",Player.Hand,"prohibitUse")) then
          return ""
        elseif trick == "fire_attack" and (tar.hp > 2 or #usefrom.player_cards[Player.Hand] > 2) then
          return ""
        elseif (trick == "archery_attack" or trick == "savage_assault") and (tar.hp > 2 or tar:getCardOrSkillByPat(dmgCards_t[trick],Player.Hand,"prohibitResponse")) then
          return ""
        elseif trick == "duel" and (tar.hp > 2 or #table.filter(tar.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end) > #table.filter(usefrom.player_cards[Player.Hand],function(cid) return Fk:getCardById(cid).trueName == "slash" end)) then
          return ""
        end
        return handleEncode(not isviewas and {card = card} or card,isviewas)
      end
    end
  end
  return ""
end
--反打无懈可击逻辑
-- local askforNulliToHandle = function (card,player,isviewas)
--   local room = player.room
--   local trick,tar = room.nuliiinfo[1],room:getPlayerById(room.nuliiinfo[2])
--   local hands,judeges = player.player_cards[Player.Hand],player.player_cards[Player.Judge]
--   local isindul = false
--   if #judeges > 0 then
--     isindul = player:hasDelayTrueTrick("indulgence")
--     if isindul then  --1个无懈且被乐了会优先保留
--       if room.current.id ~= player.id then 
--         local trickcard = Fk:cloneCard(trick)

--         if tar.hp < 2 and #tar.player_cards[Player.Hand] > 2 and trickcard.is_damage_card then 
        
--       else
--         if trick == "lightning" then return "" end
--         if isindul and trick ~= "indulgence" then --对于判定区多个锦囊牌且只有1个无邪则只对乐无邪
--           return ""
--         end
--         local data = not isviewas and {card = card} or card
--         return handleEncode(data,isviewas)
--       end
--     end
--   end
-- end
--反打无懈可击
local askforToNulliHandle = function (target,trick_card,card,player,isviewas)
  -- local trick = trick_card
  --不无懈自己或者队友
  if LangAI.ISSAMECAMP(player,target) then
    return ""
  else
    -- askforNulliHandle()
    local data = not isviewas and {card = card} or card
    return handleEncode(data,isviewas)
  end
end
--回合外使用或响应卡牌效果
local askforCommonHandle = function (self,exdata,card_name,avalicard,isviewas)
  local player,room = self.player,self.player.room
  player.isplaying = false
  return LangAI.UseCardLogicBySkill(self,not isviewas and Fk:getCardById(avalicard) or Fk:cloneCard(card_name),
    exdata)
end
--询问使用卡牌
random_cb.AskForUseCard = function(self, jsonData)
  local player,room = self.player,self.player.room
  local data = json.decode(jsonData)
  local card_name = data[1]
  local pattern = data[2] or card_name
  local usemes = data[3]
  local cancelable = data[4] or true
  local mes = data[5]
  local effectdata = data[7]
  local use_card
  local use_card_from
  local use_card_to

  if effectdata then
    if effectdata.card then
      use_card = type(effectdata.card) == "number" and Fk:getCardById(effectdata.card) or Fk:cloneCard(effectdata.card[1],effectdata.card[2],effectdata.card[3])
    end
    local oppo_strike_nulli = string.startsWith(usemes,"#AskForNullificationWithoutTo")
    if not oppo_strike_nulli then
      use_card_from = room:getPlayerById(effectdata.from)
      use_card_to = room:getPlayerById(effectdata.to)
    else
      use_card_to = room:getPlayerById(effectdata.from)
    end
  end

  if use_card and use_card.is_damage_card and effectdata then
    local invalskill = player:getMark(MarkEnum.UncompulsoryInvalidity.."-turn")
    if invalskill == 0 and (pattern=="jink" or pattern=="nullification") and (not oppo_strike_nulli and player:canSubHp(use_card_from,use_card)) then
      if pattern=="nullification" and string.startsWith(usemes,"#AskForNullification") then
        if use_card_to.id == player.id then return "" end
      else
        return ""
      end
    end
  end

  if pattern == "nullification" and use_card_from and use_card_to then --使用或者反打无懈提取无懈对象和无懈的锦囊
    if LangAI.ISSAMECAMP(player,use_card_from) and LangAI.ISSAMECAMP(player,use_card_to) and use_card_to.hp ~= 1 then return "" end
  end

  local exp = Exppattern:Parse(pattern)
  --先检测有没有转化技能
  local avail_cards = {}
  local vss = table.find(player.player_skills, function(s)
    return s:isInstanceOf(ViewAsSkill) and exp:matchExp(s.pattern) and s.enabledAtPlay and s:enabledAtPlay(player)
  end)
  if vss then
    local ret
    if LangAI.DiySkillLogic[vss.trueName] then
      ret = LangAI.DiySkillLogic[vss.trueName](self,vss,true)
    else
      ret = useVSSkill(self, vss, nil,card_name)       
    end
    if ret then table.insert(avail_cards,ret) end
  else
     --没有转化技筛选出可使用的卡
    avail_cards = table.filter(player:getCardIds("he"), function(id)
      local card = Fk:getCardById(id,true)
      card = LU:getCardsByFilterSkill(player,card)
      return exp:match(card) and not player:prohibitUse(card)
    end)
  end

  if pattern == "jink" and effectdata.fixedResponseTimes and type(avail_cards[1]) == "number" then --检测敌人有没有无双，浪无双，这种需要连续出多闪的技能
    local responjinknum = player.responjinknum or 0
    local reponsetimes = effectdata.fixedResponseTimes.jink
    if #avail_cards + responjinknum < reponsetimes and not player:hasSkill("#eight_diagram_skill") then return "" end
  end

  if #avail_cards > 0 then
    local filtercards = {}
    local mustars
    local isviewas = false

    local avalicardnum = #avail_cards
    local avalicard = table.remove(avail_cards,1)
    if type(avalicard) == "number" then
        avalicard = Fk:getCardById(avalicard)
    else
      isviewas = true
    end
    local avaldata = not isviewas and avalicard.id or avalicard
    if avalicard.trueName == "nullification" then
      -- room:delay(400)
      if string.startsWith(usemes,"#AskForNullification:") then
        return askforNulliHandle(use_card_to,use_card.trueName,avaldata,avalicardnum,player,isviewas,use_card_from)  --使用无懈可击
      elseif string.startsWith(usemes,"#AskForNullificationWithoutTo:") then
        return askforToNulliHandle(use_card_to,use_card.trueName,avaldata,player,isviewas)  --反打无懈可击
      end
    end
    if card_name == "peach" then
      return askforPeachHandle(usemes,avaldata,player,isviewas,avalicardnum)  --使用酒桃
    end 
    local ret= askforCommonHandle(self,mes,card_name,avaldata,isviewas)
    if ret then
      filtercards = not isviewas and {avalicard.id} or {avalicard}
      mustars = ret
    end
    if #filtercards > 0 then
      local data 
      if not isviewas then
        data = {card = filtercards[1],targets = mustars or {}}
      else
        if mustars then
          filtercards[1].targets = mustars
        end
        data = filtercards[1]
      end
      if pattern == "jink" and effectdata.fixedResponseTimes then
        local responjinknum = player.responjinknum or 0
        player.responjinknum = responjinknum + 1
        if player.responjinknum == effectdata.fixedResponseTimes.jink then player.responjinknum = 0 end
      end
      return handleEncode(data,isviewas)
    end
  end
  return ""
end

---@param self LangAI
---响应打出卡牌
random_cb.AskForResponseCard = function(self, jsonData)
  local player = self.player
  local room = self.room
  local data = json.decode(jsonData)
  local skill = Fk.skills[data[1]]
  local pattern = data[2]
  local promt = data[3]
  local cancelable = data[4]
  local extradata = data[5]
  local effectdata = data[7]
  local use_card 
  local use_card_from
  local use_card_to
  -- pt(effectdata)
  -- pt(data)
  -- dbg()
  if effectdata and effectdata.card then
    use_card = type(effectdata.card) == "number" and Fk:getCardById(effectdata.card) or Fk:cloneCard(effectdata.card[1],effectdata.card[2],effectdata.card[3])
    -- use_card = effectdata.card and Fk:getCardById(effectdata.card)
    use_card_from = room:getPlayerById(effectdata.from)
    use_card_to = room:getPlayerById(effectdata.to)
  else
    if skill then
      if singleOptiSkill[skill.trueName] then
        local ret = singleOptiSkill[skill.trueName](self,skill,promt,nil,{pattern=pattern})
        return ret
      end
    end
    return ""
  end

  if use_card and use_card.trueName == "duel" then
    if player.hp / player.maxHp  > 0.5 and not LangAI.ISSAMECAMP(use_card_from,player) and #use_card_from.player_cards[Player.Hand] > #player.player_cards[Player.Hand] + 2 then return "" end
    if player.hp ~= 1 and use_card_from ~= player and LangAI.ISSAMECAMP(player,use_card_from) then return "" end
  end

  local invalskill = player:getMark(MarkEnum.UncompulsoryInvalidity.."-turn")
  if invalskill == 0 and player:canSubHp(use_card_from,use_card) then
    if use_card and (use_card.trueName ~= "duel" or use_card_from ~= player) then
      return ""
    end
  end

  local exp = Exppattern:Parse(pattern)

  local vss = table.find(player.player_skills, function(s)
    if s:isInstanceOf(ViewAsSkill) and type(s.pattern) == "string" then
      return exp:matchExp(s.pattern) and s.enabledAtResponse and s:enabledAtResponse(player)
    end
  end)
  --主动视为技能看看是否有满足条件卡牌加入使用卡组
  if vss then
    local ret
    if LangAI.DiySkillLogic[vss.trueName] then
      ret = LangAI.DiySkillLogic[vss.trueName](self,vss,true)
    else
      ret = useVSSkill(self, vss, nil,pattern)       
    end
    if ret then 
      if pattern == "slash" and effectdata.fixedResponseTimes then --检测敌人有没有无双，浪无双，这种需要连续出多闪的技能
        local responslashnum = player.responslashnum or 0
        local reponsetimes = effectdata.fixedResponseTimes.slash
        player.responslashnum = responslashnum + 1
        if player.responslashnum == reponsetimes then player.responslashnum = 0 end
      end
      return handleEncode(ret,true)
    end
  else
    local avail_cards = table.filter(player:getCardIds{ Player.Hand, Player.Equip }, function(id)
      local card = Fk:getCardById(id)
      return exp:match(card) and not player:prohibitResponse(card)
    end)
    if #avail_cards > 0 then
      if pattern == "slash" and #avail_cards == 1 and (use_card and use_card~="duel") and player.maxHp > 3 and player.hp / player.maxHp > 0.5 then return "" end
  
      -- if pattern == "jink" and #avail_cards == 1 and player.maxHp > 3 and player.hp / player.maxHp > 0.5 and not LangAI.ISSAMECAMP(player,use_card_from) and use_card_from.phase == Player.Play then 
      --   for _,cid in ipairs(use_card_from.player_cards[Player.Hand]) do
      --     local card = Fk:getCardById(cid)
      --     if card.trueName == "slash" and not use_card_from:prohibitResponse(card)  then return "" end
      --   end
      -- end

      if pattern == "slash" and effectdata.fixedResponseTimes then --检测敌人有没有无双，浪无双，这种需要连续出多闪的技能
        local responslashnum = player.responslashnum or 0
        local reponsetimes = effectdata.fixedResponseTimes.slash
        if #avail_cards + responslashnum < reponsetimes then return "" end
        player.responslashnum = responslashnum + 1
        if player.responslashnum == reponsetimes then player.responslashnum = 0 end
      end
      return json.encode{
        card = table.random(avail_cards),
        targets = {},
      } 
    end
  end
  return ""
end

local handleChose = function (flag,target,player,num,self)
  local totalcards = target:getCardIds(flag)
  if #totalcards == 0 or num >= #totalcards then return totalcards end
  if LangAI.ISSAMECAMP(player,target) and string.find(flag,"j") and #target.player_cards[Player.Judge] > 0 then
    local judges = target.player_cards[Player.Judge]
    if #judges == 1 then
      return {judges[1]}
    else
      local priojudges = getJudegeData(target)
      return {priojudges[2]}
    end
  end
  --优先选择装备
  local selcards = {}
  if flag == "e" or flag == "he" or flag == "hej" then
    local equips = target:getCardIds(Player.Equip)
    local hanlecards = function(area,remain)
      local newhands = target:getCardIds(area)
      if #newhands == 0 then return {} end
      for i = 1, remain do
        if #newhands == 0 then break end
        local rand = table.random(newhands)
        table.insert(selcards,rand)
        if num == #selcards then return selcards end
        table.removeOne(newhands,rand)
      end
    end

    if #equips == 0 and string.find(flag,"h") then
      hanlecards(Player.Hand,num)
      if num == #selcards then return selcards end
    else
      local dangerwid = target:getEquipment(Card.SubtypeWeapon)
      local noselarmid = target:getEquipment(Card.SubtypeArmor)
      if dangerwid then
        local dangerw = Fk:getCardById(dangerwid)
        if DisEmyWeapons[dangerw.trueName] and #target.player_cards[Player.Hand] > 2 then
          table.insert(selcards,dangerwid)
          if #selcards == num then return selcards end
          table.removeOne(equips,dangerwid)
        end
      end
      if noselarmid then
        local noselarm = Fk:getCardById(noselarmid)
        if noselarm.trueName ~= "silver_lion" then
          table.insert(selcards,noselarmid)
          if #selcards == num then return selcards end
          table.removeOne(equips,noselarmid)
        else
          if LangAI.ISSAMECAMP(player,target) and target:isWounded() then
            table.insert(selcards,noselarmid)
            if #selcards == num then return selcards end
            table.removeOne(equips,noselarmid)
          end
          if not LangAI.ISSAMECAMP(player,target) and not target:isWounded() then
            table.insert(selcards,noselarmid)
            if #selcards == num then return selcards end
            table.removeOne(equips,noselarmid)
          end
        end
      end
      for _, subtype in ipairs(ImporEeuipsType) do
        local eid = target:getEquipment(subtype)
        if eid and not table.contains(selcards,eid) then
          local equipcard = Fk:getCardById(eid)
          if equipcard.sub_type == Card.SubtypeDefensiveRide and (target.hp > 1 or not player:inMyAttackRange(target)) then --and player:distanceTo(target) ~= 1
            table.insert(selcards,eid)
            table.removeOne(equips,eid)
          end         
          if equipcard.sub_type == Card.SubtypeTreasure and target.hp > 1 then 
            table.insert(selcards,eid) 
            table.removeOne(equips,eid)            
          end
          if equipcard.sub_type == Card.SubtypeArmor then
            if equipcard.trueName ~= "silver_lion" then
              table.insert(selcards,eid) 
              table.removeOne(equips,eid)
            end
          end
          if equipcard.sub_type == Card.SubtypeWeapon and target.hp > 2 and #target.player_cards[Player.Hand] > 2 and (DisEmyWeapons[equipcard.trueName] or not target:inMyAttackRange(player,-equipcard.attack_range + 1)) then 
            table.insert(selcards,eid)
            table.removeOne(equips,eid)
          end
          if equipcard.sub_type == Card.SubtypeOffensiveRide and target:distanceTo(player) == 1 and player:getEquipment(Card.SubtypeDefensiveRide) then 
            table.insert(selcards,eid)
            table.removeOne(equips,eid)
          end
        end
        if #selcards == num then return selcards end
      end
    end
    if num - #selcards > 0 and string.find(flag,"h") then
      hanlecards(Player.Hand,num - #selcards)
      if num == #selcards then return selcards end
    end
    if num - #selcards > 0 and string.find(flag,"e") then
      hanlecards(Player.Equip,num - #selcards)
      if num == #selcards then return selcards end
    end
    if num - #selcards > 0 and string.find(flag,"j") then
      hanlecards(Player.Judge,num - #selcards)
      if num == #selcards then return selcards end
    end
    return selcards
  else
    if flag == "h" then
      local newhands = target:getCardIds(Player.Hand)
      for i = 1, num do
        local rand = table.random(newhands)
        table.insert(selcards,rand)
        table.removeOne(newhands,rand)
      end
      return selcards
    end
    if flag == "j" then
      local newjudges = target:getCardIds(Player.Judge)
      for i = 1, num do
        local rand = table.random(newjudges)
        table.insert(selcards,rand)
        table.removeOne(newjudges,rand)
      end
      return selcards
    end
  end
end
--移动区域牌
random_cb.AskForMoveCardInBoard = function(self, jsonData)
  local data = json.decode(jsonData)
  local room = self.room
  local player = self.player
  if #data.cards == 0 then return "" end
  local playerIds = data.playerIds
  local friend = room:getPlayerById(playerIds[2]) --可能移动乐兵，是敌人
  local enemy = room:getPlayerById(playerIds[1]) --可能移动乐兵，是队友
  if not friend or not enemy then return "" end
  local carddatas = {}
  for _,cid in ipairs(data.cards) do
    local card = Fk:getCardById(cid)
    table.insert(carddatas,card)
    if card.sub_type == Card.SubtypeDelayedTrick and MoveDelaySeqs[card.trueName] and LangAI.ISSAMECAMP(room:getCardOwner(cid),player) then
      local mes = getJudegeData(enemy)
      if #mes > 0 then return json.encode{cardId = mes[2],pos = 0} end
    end
  end
  local sort_t = {}
  for _,t in ipairs(MoveEQSeqs) do
    for i,c in ipairs(carddatas) do
      if c.sub_type == t then
        table.insert(sort_t,c)
      end
    end
  end
  for _,c in ipairs(sort_t) do
    if not friend:getEquipment(c.sub_type) then
      return json.encode{
        cardId = c.id,
        pos = 0
      }
    end
  end
  return ""
end
--选择别人的单卡
random_cb.AskForCardChosen = function(self, jsonData)
  local data = json.decode(jsonData)
  local room = self.room
  local player = self.player
  local tarid = data[1]
  local flag = data[2]
  local num = 1
  local skillname = data[3]
  local target = room:getPlayerById(tarid)
  if target then
    if type(flag) == "string" then
      if target:isNude() then
        return "__cancel"
      end
      local ret = handleChose(flag,target,player,num,self)
      if ret and #ret > 0 then
        return ret[1]
      end
      return ""
    else
      if flag.card_data[1] and flag.card_data[1][1] == "jiqiaos" then --激峭
        local cards_red,cards_black = {},{}
        for _,cid in ipairs(flag.card_data[1][2]) do
          local card = Fk:getCardById(cid)
          if card.color == Card.Red then
            table.insert(cards_red,cid)
          else
            table.insert(cards_black,cid)
          end
        end
        if target.hp < 2 and (#cards_black - #cards_red > 1 or #cards_red - #cards_black > 1) then return "__cancel" end
        local prioSelCard = function(prio_t)
          local ret = table.find(prio_t,function(cid) return target:canUse(Fk:getCardById(cid)) end)
          return not ret and getSelCardsSeq(prio_t,1,selcards_prio_t)[1] or ret
        end
        if not target:isWounded() then
          return prioSelCard(table.clone(flag.card_data[1][2]))
        else
          return #cards_black >= #cards_red and prioSelCard(cards_black) or prioSelCard(cards_red)
        end
      end
      local handcards = {}
      for _, t in ipairs(flag.card_data) do
        table.insertTable(handcards, t[2])
      end
      if #handcards == 0 then return "__cancel" end
      return handcards[math.random(1, #handcards)]
    end
  else
    return "__cancel"
  end
end
--选择别人的多卡
random_cb.AskForCardsChosen = function(self, data)
  local player = self.player
  local room = player.room
  -- local data = json.decode(jsonData)
  local extra_data = data.extra_data
  local tarid = extra_data.to
  local max = extra_data.max
  local flag = ""
  if type(data.data[1][1]) == "string" and string.startsWith(data.data[1][1],"$") then
    for _,st in ipairs(data.data) do
      if st[1] == "$Hand" then flag = flag + "h" end
      if st[1] == "$Equip" then flag = flag + "e" end
      if st[1] == "$Judge" then flag = flag + "j" end
    end
  else
    flag = data.data
  end
  if flag == "" then return "__cancel" end
  local skillname = extra_data.skillName
  local target = room:getPlayerById(tarid)
  if target then
    if type(flag) == "string" then
      if target:isNude() then
        return "__cancel"
      end
      local ret = handleChose(flag,target,player,max,self)
      if ret and #ret > 0 then
        return json.encode(ret)
      end
      return ""
    else
      if type(flag) == "table" then
        if flag and #flag > 0 and skillname then
          local bottomcards = flag[1][2]
          if not bottomcards or type(bottomcards) ~= "table" or #bottomcards == 0 then return "" end
          local ret = {}
          if skillname == "cangxin" then
            ret = bottomcards
          end
          if skillname == "juetao" then
            ret = bottomcards
          end
          return #ret > 0 and json.encode(ret) or ""
        end
      end
    end
  end
  return "__cancel"
end
--卡牌选框逻辑（自定义）
-- {
--   data = { { { 902, 120, 820, 795, 813 }, {}, {} }, "#yuqi", 0, { 5, 1, 5 }, { 0, 1, 1 }, false, { "Top", "caojinyu", "caojinyu" }, ".", "", false },
--   path = "packages/utility/qml/ArrangeCardsBox.qml"
-- }
random_cb.AskForArrangeCards = function(self, jsonData)
  local player = self.player
  local room = player.room
  local data = json.decode(jsonData)
  local cards,prompt,cardsmes = data.cards,data.prompt,data.capacities
  if cards and data.poxi_type and cardsmes and data.poxi_type == "chengxiang_count" then
    local selnum = cardsmes[1]
    cards = table.clone(cards[1])
    local sortnums = table.map(cards,function(cid) return Fk:getCardById(cid) end)
    table.sort(sortnums,function(a,b) return a.number < b.number end)
    local cntnum = 0
    local cntcards = {}
    for _,card in ipairs(sortnums) do
      cntnum = card.number + cntnum
      if cntnum <= 13 then 
        table.insert(cntcards,card.id) 
        table.removeOne(cards,card.id)
      end
    end
    if #cntcards == 1 then
      table.insert(cards,cntcards[1])
      cntcards = getSelCardsSeq(cards,1,selcards_prio_t)
    end
    return json.encode({cards,cntcards})
  end
  if cards and prompt and prompt == "#yuqi" then
    cards = table.clone(cards[1])
    local getcards_damager = getSelCardsSeq(cards,1,discards_prio_slashs_t)
    local getcards_self = getSelCardsSeq(cards,math.min(cardsmes[3],#cards),selcards_prio_t)
    local ret = {cards,getcards_damager,getcards_self}
    return json.encode(ret)
  end
end
random_cb.CustomDialog = function(self, jsonData)
  local player = self.player
  local room = player.room
  local data = json.decode(jsonData)
  data = data.data
  if data and data[2] and data[2][1] == "ty_ex__xuanhuo_use" then
    local cards,promt= data[1],data[3] 
    local indx = string.find(promt,"%d:") 
    local tarid = tonumber(string.sub(promt,indx+2,#promt))
    local fireslash,duel
    for _, cid in ipairs(cards) do
      local card = Fk:getCardById(cid)
      if card.name == "fire__slash" then fireslash = cid end
      if card.name == "duel" then duel = cid end
    end
    local tar = room:getPlayerById(tarid)
    local slashs = LU:getPlayerCardNameIds(player,"h",{"slash"})
    local emyslashs = LU:getPlayerCardNameIds(tar,"h",{"slash"})
    if #slashs.slash >= #emyslashs.slash then
      return json.encode({cards = {duel}})
    else
      return json.encode({cards = {fireslash}})
    end
  end
end
-- random_cb.CustomDialog = function(self, jsonData)
--   local player = self.player
--   local room = player.room
--   local data = json.decode(jsonData)
--   local data = data.data
  -- if eventdata and eventdata[3] and eventdata[3].name == "qianlong" then
  --   local ret = {{},{}}
  --   local max_top_cards = cardsmes[2]
  --   local linkskill = "juetao"
  --   local nouse_juetao = table.find(player.player_skills,function(s)
  --     if s.trueName == linkskill and player:usedSkillTimes(linkskill, Player.HistoryGame) == 0 then return true end
  --   end)
  --   local getcards = {"jink","nullification","collateral","analeptic","peach","supply_shortage","indulgence"}
  --   local slashs = {}
  --   local botomcards = table.clone(cards)
  --   for _,id in ipairs(cards) do
  --     local card = Fk:getCardById(id)
  --     if nouse_juetao and table.contains(getcards,card.trueName) then table.insert(ret[2],id) table.removeOne(botomcards,id) end
  --     if max_top_cards == #ret[2] then break end
  --   end
  --   local remain = max_top_cards - #ret[2]
  --   if remain > 0 then 
  --     if nouse_juetao then
  --       local slashs = {}
  --       for _,id in ipairs(botomcards) do
  --         local card = Fk:getCardById(id)
  --         if card.trueName ~= "slash" then table.insert(ret[2],id) else table.insert(slashs,id) end
  --         if max_top_cards == #ret[2] then break end
  --       end
  --       ret[1] = slashs
  --     else 
  --       for _,id in ipairs(cards) do
  --         table.insert(ret[1],id) 
  --         table.removeOne(botomcards,id)
  --         if max_top_cards == #ret[1] then break end
  --       end
  --       ret[1] = botomcards
  --     end
  --   end
  --   return json.encode(ret)
  -- end
-- end
--卡牌选框逻辑（观星）
random_cb.AskForGuanxing = function(self, jsonData)
  local player = self.player
  local room = player.room
  local data = json.decode(jsonData)
  local min_top_cards = data.min_top_cards
  local max_top_cards = data.max_top_cards
  local min_bottom_cards = data.min_bottom_cards
  local max_bottom_cards = data.max_bottom_cards
  local top_area_name = data.top_area_name
  local bottom_area_name = data.bottom_area_name
  local cards = data.cards
  local eventdata = room.logic:getCurrentEvent().data
  if eventdata and eventdata[3] and eventdata[3].name == "qianlong" then
    cards = cards[1]
    local ret = {{},{}}
    local linkskill = "juetao"
    local nouse_juetao = table.find(player.player_skills,function(s)
      if s.trueName == linkskill and player:usedSkillTimes(linkskill, Player.HistoryGame) == 0 then return true end
    end)
    local getcards = {"jink","nullification","collateral","analeptic","peach","supply_shortage","indulgence"}
    local slashs = {}
    local botomcards = table.clone(cards)
    for _,id in ipairs(cards) do
      local card = Fk:getCardById(id)
      if nouse_juetao and table.contains(getcards,card.trueName) then table.insert(ret[2],id) table.removeOne(botomcards,id) end
      if max_bottom_cards == #ret[2] then break end
    end
    local remain = max_bottom_cards - #ret[2]
    if remain > 0 then 
      if nouse_juetao then
        local slashs = {}
        for _,id in ipairs(botomcards) do
          local card = Fk:getCardById(id)
          if card.trueName ~= "slash" then table.insert(ret[2],id) else table.insert(slashs,id) end
          if max_bottom_cards == #ret[2] then break end
        end
        ret[1] = slashs
      else 
        for _,id in ipairs(cards) do
          table.insert(ret[2],id) 
          table.removeOne(botomcards,id)
          if max_bottom_cards == #ret[2] then break end
        end
        ret[1] = botomcards
      end
    end
    return json.encode(ret)
  end
  if min_top_cards == max_bottom_cards and min_bottom_cards == max_bottom_cards then
    local getcards = getSelCardsSeq(cards,2,selcards_prio_t)
    local ret = {getcards,cards}
    return json.encode(ret)
  end
  return  "__cancel"
end
--卡牌选框逻辑（五谷丰登）
random_cb.AskForAG = function(self, jsonData)
  local player = self.player
  local room = player.room
  local data = json.decode(jsonData)
  if data[3] == "amazing_grace_skill" then
    local cards = data[1]
    local getcard = getSelCardsSeq(cards,1,selcards_prio_t)
    if #getcard > 0 then
      return getcard[1]
    else
      return ""
    end
  end
end
--卡牌选框逻辑（破袭）
local handlePoxiSuit = function(whohands) --处理破袭花色
  local whosuits = {{},{}} --第1个空表是存已有花色，第2个是缺少的花色
  for _,cid in ipairs(whohands) do
    local card = Fk:getCardById(cid)
    if not whosuits[1][tostring(card.suit)] then
      whosuits[1][tostring(card.suit)] = cid
    end
  end
  if #whosuits[1] < 4 then
    for i = 1,4 do
      local inxstr = tostring(i)
      if not whosuits[1][inxstr] then
        whosuits[2][inxstr] = i
      end
    end
  end
  return whosuits
end
local handlepoxiCode = function(whosuits) --处理发送的破袭花色id数据
  local ret = {}
  for i, v in pairs(whosuits) do
    table.insert(ret, v)
  end
  return #ret == 4 and ret or nil --不满足四花色就取消
end
random_cb.AskForPoxi = function(self, jsonData)
  local player = self.player
  local room = player.room
  local data = json.decode(jsonData)
  if data.type and data.type == "AskForCardsChosen" then
    return self.cb_table[data.type](self,data)
  end
  local poxidata = data.data
  local playerhands = player.player_cards[Player.Hand]
  local enemyhands = poxidata and poxidata[2] and poxidata[2][2]
  if not enemyhands or #enemyhands == 0 then return "__cancel" end
  local playersuits = handlePoxiSuit(playerhands)
  local enemysuits = handlePoxiSuit(enemyhands)
  local hdlfillsuit = function(onesuits,twosuits) --第一个参数是敌人手牌花色表，缺什么花色能补就从第2个ai手牌表参数补
    for suit,suit_v in pairs(onesuits[2]) do
      if twosuits[1][suit] then
        onesuits[1][suit] = twosuits[1][suit]
      end
    end
  end
  local discardfill = function(discardsuits,fillsuits) --给第一个参数的花色数拆1补1
    local prhavesuits = fillsuits[1]
    local dishavesuits = discardsuits[1]
    local disnosuits = discardsuits[2]
    if next(disnosuits) then
      local fillsuitids = {}
      for s,v in pairs(disnosuits) do
        if prhavesuits[s] then fillsuitids[s] = prhavesuits[s] end
      end
      for s,v in pairs(prhavesuits) do
        if dishavesuits[s] then fillsuitids[s] = v break end
      end
      for s,v in pairs(fillsuitids) do
        dishavesuits[s] = v 
      end
      local ret = handlepoxiCode(discardsuits[1])
      if ret then return json.encode(ret) end
    else
      local id = prhavesuits["1"] or prhavesuits["2"] or prhavesuits["3"] or prhavesuits["4"]
      if id then
        local card = Fk:getCardById(id)
        local subsuit = card.suit
        discardsuits[1][tostring(subsuit)] = nil
        discardsuits[2][tostring(subsuit)] = 1
        hdlfillsuit(discardsuits,fillsuits)
        local ret = handlepoxiCode(discardsuits[1])
        if ret then return json.encode(ret) end
      end
    end
  end
  --拆ai牌
  local pn = LangAI.CNTTNUM(playersuits[1])
  if pn >= 3 and player.hp < 3 then --ai有四花色情况下，ai血量过低优先拆敌3牌
    if pn == 3 then
      hdlfillsuit(playersuits,enemysuits)
      local ret = handlepoxiCode(playersuits[1])
      if ret then return json.encode(ret) end
    else
      local result = discardfill(playersuits,enemysuits)
      if result then return result end 
    end
  end
  --拆敌人牌
  local en = LangAI.CNTTNUM(enemysuits[1])
  if en ~= 3 then --尽量避免拆敌人牌3花色
    if en == 1 and pn == 3 and (player.hp == player.maxHp or #playerhands < 9) then --极端情况下点取消
      return "[]"
    end
  else
    if #playerhands > 2 then  --如果牌多互拆2-2花色，牌少就不22，尽量能拆敌3己1
      local result = discardfill(enemysuits,playersuits)
      if result then return result end 
      return "[]" 
    end
  end
  hdlfillsuit(enemysuits,playersuits)
  local ret = handlepoxiCode(enemysuits[1])
  if ret then return json.encode(ret) end
  return "[]"
end

---@param self LangAI
--出牌阶段使用卡牌
random_cb.PlayCard = function(self, jsonData)
  local player,room = self.player,self.player.room
  player.hand_slashnum = 0
  player.hand_analepnum = 0
  local cardskills = {}
  for _,cid in ipairs(player.player_cards[Player.Hand]) do
    local card = Fk:getCardById(cid,true)
    card = LU:getCardsByFilterSkill(player,card)
    if player:canUse(card) then 
      table.insert(cardskills,card)
      if card.trueName == "slash" then player.hand_slashnum = player.hand_slashnum + 1 end
      if card.trueName == "analeptic" then player.hand_analepnum = player.hand_analepnum + 1 end
    end
  end
  for _,s in ipairs(player.player_skills) do
    if not self.BLACKSKILLS[s.trueName] then
      if s:isInstanceOf(ActiveSkill) and s.canUse and s:canUse(player) then table.insert(cardskills,s) end
      if s:isInstanceOf(ViewAsSkill) and s.enabledAtPlay and s:enabledAtPlay(player) then table.insert(cardskills,s) end
    end
  end
  table.sort(cardskills,function(a,b)  --带有某些技能可以改变某些牌的优先级
    local aret = a.prio or 0
    local bret = b.prio or 0
    if player.changecardprio then
      aret = player.changecardprio[a.trueName] or aret
      bret = player.changecardprio[b.trueName] or bret
    end 
    return aret > bret
  end)

  local pos = 1
  while #cardskills > 0 and pos <= #cardskills do
    local cardandskill = cardskills[pos]
    local actret
    if cardandskill:isInstanceOf(Card) then
      local logicname = cardandskill.type ~= Card.TypeEquip and cardandskill.trueName or "equiplogic"
      local ret,ret1,retcard
      local uselogicfunc = LangAI.UseCardLogic[logicname]
      player.isplaying = true
      if uselogicfunc then       
        ret,ret1,retcard = uselogicfunc(self,cardandskill)
      else
        ret,ret1,retcard = LangAI.UseCardLogic["commonuselogic"](self,cardandskill)
      end
      player.isplaying = false
      if ret then 
        return EncodeByPlayCard(retcard or cardandskill,ret,ret1) 
      end
    elseif cardandskill:isInstanceOf(ActiveSkill) then
      if not singleOptiSkill[cardandskill.name] then
        actret = useActiveSkill(self, cardandskill, nil)
      else
        actret = singleOptiSkill[cardandskill.name](self,cardandskill)
      end
      if actret then return actret end 
    elseif cardandskill:isInstanceOf(ViewAsSkill) then
      if not singleOptiSkill[cardandskill.name] then
        actret = useVSSkill(self, cardandskill, nil)
      else
        actret = singleOptiSkill[cardandskill.name](self,cardandskill)
      end
      if actret then return actret end 
    end
    pos = pos + 1
  end
  return ""
end

function LangAI:initialize(player)
  AI.initialize(self, player)
  self.cb_table = random_cb
end

return LangAI
